3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/bios.c
5 * PURPOSE: BIOS Access Routines
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 UCHAR HalpIopmSaveBuffer
[0x2000];
19 HARDWARE_PTE HalpSavedPte
;
22 USHORT HalpSavedIopmBase
;
23 PUCHAR HalpSavedIoMap
;
26 #define GetPdeAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 22) << 2) + 0xC0300000)
27 #define GetPteAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 12) << 2) + 0xC0000000)
29 /* FUNCTIONS ******************************************************************/
33 HalpStoreAndClearIopm(IN PUCHAR IoMap
)
37 /* Backup the old I/O Map */
38 RtlCopyMemory(HalpIopmSaveBuffer
, IoMap
, 0x2000);
40 /* Erase the current one */
41 for (i
= 0; i
< 0x2000; i
++) IoMap
[i
] = 0;
42 for (i
= 0x2000; i
< 0x2004; i
++) IoMap
[i
] = 0xFF;
47 HalpRestoreIopm(IN PUCHAR IoMap
)
51 /* Restore the backed up copy, and initialize it */
52 RtlCopyMemory(IoMap
, HalpIopmSaveBuffer
, 0x2000);
53 for (i
= 0x2000; i
< 0x2004; i
++) IoMap
[i
] = 0xFF;
58 HalpMapRealModeMemory(VOID
)
60 PHARDWARE_PTE Pte
, V86Pte
;
63 /* Get the page table directory for the lowest meg of memory */
64 Pte
= GetPdeAddress(0);
65 HalpSavedPfn
= Pte
->PageFrameNumber
;
68 /* Map it to the HAL reserved region and make it valid */
72 Pte
->PageFrameNumber
= (GetPdeAddress(0xFFC00000))->PageFrameNumber
;
74 /* Flush the TLB by resetting CR3 */
75 __writecr3(__readcr3());
77 /* Now loop the first meg of memory */
78 for (i
= 0; i
< 0x100000; i
+= PAGE_SIZE
)
81 Pte
= GetPteAddress((PVOID
)i
);
82 Pte
->PageFrameNumber
= i
>> PAGE_SHIFT
;
88 /* Now get the entry for our real mode V86 code and the target */
89 Pte
= GetPteAddress(0x20000);
90 V86Pte
= GetPteAddress(&HalpRealModeStart
);
93 /* Map the physical address into our real-mode region */
94 Pte
->PageFrameNumber
= V86Pte
->PageFrameNumber
;
96 /* Keep going until we've reached the end of our region */
99 } while (V86Pte
<= GetPteAddress(&HalpRealModeEnd
));
101 /* Flush the TLB by resetting CR3 */
102 __writecr3(__readcr3());
107 HalpSwitchToRealModeTrapHandlers(VOID
)
111 /* Save the current Invalid Opcode and General Protection Fault Handlers */
112 HalpGpfHandler
= ((((PKIPCR
)KeGetPcr())->IDT
[13].ExtendedOffset
<< 16) &
114 (((PKIPCR
)KeGetPcr())->IDT
[13].Offset
& 0xFFFF);
115 HalpBopHandler
= ((((PKIPCR
)KeGetPcr())->IDT
[6].ExtendedOffset
<< 16) &
117 (((PKIPCR
)KeGetPcr())->IDT
[6].Offset
& 0xFFFF);
119 /* Now set our own GPF handler to handle exceptions while in real mode */
120 Handler
= (ULONG_PTR
)HalpTrap0D
;
121 ((PKIPCR
)KeGetPcr())->IDT
[13].ExtendedOffset
=
122 (USHORT
)((Handler
>> 16) & 0xFFFF);
123 ((PKIPCR
)KeGetPcr())->IDT
[13].Offset
= (USHORT
)Handler
;
125 /* And our own invalid opcode handler to detect the BOP to get us out */
126 Handler
= (ULONG_PTR
)HalpTrap06
;
127 ((PKIPCR
)KeGetPcr())->IDT
[6].ExtendedOffset
=
128 (USHORT
)((Handler
>> 16) & 0xFFFF);
129 ((PKIPCR
)KeGetPcr())->IDT
[6].Offset
= (USHORT
)Handler
;
134 HalpSetupRealModeIoPermissionsAndTask(VOID
)
136 /* Save a copy of the I/O Map and delete it */
137 HalpSavedIoMap
= (PUCHAR
)&(KeGetPcr()->TSS
->IoMaps
[0]);
138 HalpStoreAndClearIopm(HalpSavedIoMap
);
140 /* Save the IOPM and switch to the real-mode one */
141 HalpSavedIopmBase
= KeGetPcr()->TSS
->IoMapBase
;
142 KeGetPcr()->TSS
->IoMapBase
= KiComputeIopmOffset(1);
144 /* Save our stack pointer */
145 HalpSavedEsp0
= KeGetPcr()->TSS
->Esp0
;
150 HalpRestoreTrapHandlers(VOID
)
152 /* We're back, restore the handlers we over-wrote */
153 ((PKIPCR
)KeGetPcr())->IDT
[13].ExtendedOffset
=
154 (USHORT
)((HalpGpfHandler
>> 16) & 0xFFFF);
155 ((PKIPCR
)KeGetPcr())->IDT
[13].Offset
= (USHORT
)HalpGpfHandler
;
156 ((PKIPCR
)KeGetPcr())->IDT
[6].ExtendedOffset
=
157 (USHORT
)((HalpBopHandler
>> 16) & 0xFFFF);
158 ((PKIPCR
)KeGetPcr())->IDT
[6].Offset
= (USHORT
)HalpBopHandler
;
163 HalpRestoreIoPermissionsAndTask(VOID
)
165 /* Restore the stack pointer */
166 KeGetPcr()->TSS
->Esp0
= HalpSavedEsp0
;
168 /* Restore the I/O Map */
169 HalpRestoreIopm(HalpSavedIoMap
);
171 /* Restore the IOPM */
172 KeGetPcr()->TSS
->IoMapBase
= HalpSavedIopmBase
;
177 HalpUnmapRealModeMemory(VOID
)
182 /* Loop the first meg of memory */
183 for (i
= 0; i
< 0x100000; i
+= PAGE_SIZE
)
185 /* Invalidate each PTE */
186 Pte
= GetPteAddress((PVOID
)i
);
190 Pte
->PageFrameNumber
= 0;
193 /* Restore the PDE for the lowest megabyte of memory */
194 Pte
= GetPdeAddress(0);
196 Pte
->PageFrameNumber
= HalpSavedPfn
;
198 /* Flush the TLB by resetting CR3 */
199 __writecr3(__readcr3());
204 HalpBiosDisplayReset(VOID
)
207 PHARDWARE_PTE IdtPte
;
208 BOOLEAN RestoreWriteProtection
= FALSE
;
210 /* Disable interrupts */
211 Flags
= __readeflags();
214 /* Map memory available to the V8086 real-mode code */
215 HalpMapRealModeMemory();
218 * On P5, the first 7 entries of the IDT are write protected to work around
219 * the cmpxchg8b lock errata. Unprotect them here so we can set our custom
220 * invalid op-code handler.
222 if (KeGetCurrentPrcb()->CpuType
== 5)
224 /* Get the PTE and check if it is has been write protected yet */
225 IdtPte
= GetPteAddress(((PKIPCR
)KeGetPcr())->IDT
);
226 if (IdtPte
->Write
== 0)
228 /* Remove the protection and flush the TLB */
230 __writecr3(__readcr3());
231 RestoreWriteProtection
= TRUE
;
235 /* Use special invalid opcode and GPF trap handlers */
236 HalpSwitchToRealModeTrapHandlers();
238 /* Configure the IOPM and TSS */
239 HalpSetupRealModeIoPermissionsAndTask();
241 /* Now jump to real mode */
244 /* Restore kernel trap handlers */
245 HalpRestoreTrapHandlers();
247 /* Check if we removed the write protection before */
248 if (RestoreWriteProtection
)
250 /* Get the PTE, restore the write protection and flush the TLB */
251 IdtPte
= GetPteAddress(((PKIPCR
)KeGetPcr())->IDT
);
253 __writecr3(__readcr3());
256 /* Restore TSS and IOPM */
257 HalpRestoreIoPermissionsAndTask();
259 /* Restore low memory mapping */
260 HalpUnmapRealModeMemory();
262 /* Restore interrupts if they were previously enabled */
263 __writeeflags(Flags
);