2 * PROJECT: ReactOS Hardware Abstraction Layer (HAL)
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: halx86/generic/bios.c
5 * PURPOSE: BIOS Access Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
18 HARDWARE_PTE HalpSavedPte
;
22 USHORT HalpSavedIopmBase
;
23 PUSHORT HalpSavedIoMap
;
24 USHORT HalpSavedIoMapData
[32][2];
25 ULONG HalpSavedIoMapEntries
;
27 #define GetPdeAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 22) << 2) + 0xC0300000)
28 #define GetPteAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 12) << 2) + 0xC0000000)
30 /* FUNCTIONS ******************************************************************/
34 HalpStoreAndClearIopm(VOID
)
37 PUSHORT Entry
= HalpSavedIoMap
;
42 for (i
= j
= 0; i
< (IOPM_SIZE
) / 2; i
++)
45 // Check for non-FFFF entry
53 HalpSavedIoMapData
[j
][0] = i
;
54 HalpSavedIoMapData
[j
][1] = *Entry
;
66 while (i
++ < (IOPM_FULL_SIZE
/ 2)) *Entry
++ = 0xFFFF;
69 // Return the entries we saved
71 HalpSavedIoMapEntries
= j
;
78 ULONG i
= HalpSavedIoMapEntries
;
83 RtlFillMemory(HalpSavedIoMap
, 0xFF, IOPM_FULL_SIZE
);
86 // Restore the backed up copy, and initialize it
88 while (i
--) HalpSavedIoMap
[HalpSavedIoMapData
[i
][0]] = HalpSavedIoMapData
[i
][1];
93 HalpMapRealModeMemory(VOID
)
95 PHARDWARE_PTE Pte
, V86Pte
;
98 /* Get the page table directory for the lowest meg of memory */
99 Pte
= GetPdeAddress(0);
100 HalpSavedPfn
= Pte
->PageFrameNumber
;
103 /* Map it to the HAL reserved region and make it valid */
107 Pte
->PageFrameNumber
= (GetPdeAddress(0xFFC00000))->PageFrameNumber
;
109 /* Flush the TLB by resetting CR3 */
110 __writecr3(__readcr3());
112 /* Now loop the first meg of memory */
113 for (i
= 0; i
< 0x100000; i
+= PAGE_SIZE
)
115 /* Identity map it */
116 Pte
= GetPteAddress((PVOID
)i
);
117 Pte
->PageFrameNumber
= i
>> PAGE_SHIFT
;
123 /* Now get the entry for our real mode V86 code and the target */
124 Pte
= GetPteAddress(0x20000);
125 V86Pte
= GetPteAddress(&HalpRealModeStart
);
128 /* Map the physical address into our real-mode region */
129 Pte
->PageFrameNumber
= V86Pte
->PageFrameNumber
;
131 /* Keep going until we've reached the end of our region */
134 } while (V86Pte
<= GetPteAddress(&HalpRealModeEnd
));
136 /* Flush the TLB by resetting CR3 */
137 __writecr3(__readcr3());
142 HalpSwitchToRealModeTrapHandlers(VOID
)
146 /* Save the current Invalid Opcode and General Protection Fault Handlers */
147 HalpGpfHandler
= ((((PKIPCR
)KeGetPcr())->IDT
[13].ExtendedOffset
<< 16) &
149 (((PKIPCR
)KeGetPcr())->IDT
[13].Offset
& 0xFFFF);
150 HalpBopHandler
= ((((PKIPCR
)KeGetPcr())->IDT
[6].ExtendedOffset
<< 16) &
152 (((PKIPCR
)KeGetPcr())->IDT
[6].Offset
& 0xFFFF);
154 /* Now set our own GPF handler to handle exceptions while in real mode */
155 Handler
= (ULONG_PTR
)HalpTrap0D
;
156 ((PKIPCR
)KeGetPcr())->IDT
[13].ExtendedOffset
=
157 (USHORT
)((Handler
>> 16) & 0xFFFF);
158 ((PKIPCR
)KeGetPcr())->IDT
[13].Offset
= (USHORT
)Handler
;
160 /* And our own invalid opcode handler to detect the BOP to get us out */
161 Handler
= (ULONG_PTR
)HalpTrap06
;
162 ((PKIPCR
)KeGetPcr())->IDT
[6].ExtendedOffset
=
163 (USHORT
)((Handler
>> 16) & 0xFFFF);
164 ((PKIPCR
)KeGetPcr())->IDT
[6].Offset
= (USHORT
)Handler
;
169 HalpSetupRealModeIoPermissionsAndTask(VOID
)
171 /* Save a copy of the I/O Map and delete it */
172 HalpSavedIoMap
= (PUSHORT
)&(KeGetPcr()->TSS
->IoMaps
[0]);
173 HalpStoreAndClearIopm();
175 /* Save the IOPM and switch to the real-mode one */
176 HalpSavedIopmBase
= KeGetPcr()->TSS
->IoMapBase
;
177 KeGetPcr()->TSS
->IoMapBase
= KiComputeIopmOffset(1);
179 /* Save our stack pointer */
180 HalpSavedEsp0
= KeGetPcr()->TSS
->Esp0
;
185 HalpRestoreTrapHandlers(VOID
)
187 /* We're back, restore the handlers we over-wrote */
188 ((PKIPCR
)KeGetPcr())->IDT
[13].ExtendedOffset
=
189 (USHORT
)((HalpGpfHandler
>> 16) & 0xFFFF);
190 ((PKIPCR
)KeGetPcr())->IDT
[13].Offset
= (USHORT
)HalpGpfHandler
;
191 ((PKIPCR
)KeGetPcr())->IDT
[6].ExtendedOffset
=
192 (USHORT
)((HalpBopHandler
>> 16) & 0xFFFF);
193 ((PKIPCR
)KeGetPcr())->IDT
[6].Offset
= (USHORT
)HalpBopHandler
;
198 HalpRestoreIoPermissionsAndTask(VOID
)
200 /* Restore the stack pointer */
201 KeGetPcr()->TSS
->Esp0
= HalpSavedEsp0
;
203 /* Restore the I/O Map */
206 /* Restore the IOPM */
207 KeGetPcr()->TSS
->IoMapBase
= HalpSavedIopmBase
;
212 HalpUnmapRealModeMemory(VOID
)
217 /* Loop the first meg of memory */
218 for (i
= 0; i
< 0x100000; i
+= PAGE_SIZE
)
220 /* Invalidate each PTE */
221 Pte
= GetPteAddress((PVOID
)i
);
225 Pte
->PageFrameNumber
= 0;
228 /* Restore the PDE for the lowest megabyte of memory */
229 Pte
= GetPdeAddress(0);
231 Pte
->PageFrameNumber
= HalpSavedPfn
;
233 /* Flush the TLB by resetting CR3 */
234 __writecr3(__readcr3());
239 HalpBiosDisplayReset(VOID
)
242 PHARDWARE_PTE IdtPte
;
243 BOOLEAN RestoreWriteProtection
= FALSE
;
245 /* Disable interrupts */
246 Flags
= __readeflags();
249 /* Map memory available to the V8086 real-mode code */
250 HalpMapRealModeMemory();
253 * On P5, the first 7 entries of the IDT are write protected to work around
254 * the cmpxchg8b lock errata. Unprotect them here so we can set our custom
255 * invalid op-code handler.
257 if (KeGetCurrentPrcb()->CpuType
== 5)
259 /* Get the PTE and check if it is has been write protected yet */
260 IdtPte
= GetPteAddress(((PKIPCR
)KeGetPcr())->IDT
);
261 if (IdtPte
->Write
== 0)
263 /* Remove the protection and flush the TLB */
265 __writecr3(__readcr3());
266 RestoreWriteProtection
= TRUE
;
270 /* Use special invalid opcode and GPF trap handlers */
271 HalpSwitchToRealModeTrapHandlers();
273 /* Configure the IOPM and TSS */
274 HalpSetupRealModeIoPermissionsAndTask();
276 /* Now jump to real mode */
279 /* Restore kernel trap handlers */
280 HalpRestoreTrapHandlers();
282 /* Check if we removed the write protection before */
283 if (RestoreWriteProtection
)
285 /* Get the PTE, restore the write protection and flush the TLB */
286 IdtPte
= GetPteAddress(((PKIPCR
)KeGetPcr())->IDT
);
288 __writecr3(__readcr3());
291 /* Restore TSS and IOPM */
292 HalpRestoreIoPermissionsAndTask();
294 /* Restore low memory mapping */
295 HalpUnmapRealModeMemory();
297 /* Restore interrupts if they were previously enabled */
298 __writeeflags(Flags
);