3 * LICENSE: GPL, See COPYING in the top level directory
4 * FILE: hal/halx86/generic/amd64/x86bios.c
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
9 /* INCLUDES ******************************************************************/
17 /* This page serves as fallback for pages used by Mm */
18 #define DEFAULT_PAGE 0x21
20 /* GLOBALS *******************************************************************/
22 BOOLEAN x86BiosIsInitialized
;
23 LONG x86BiosBufferIsAllocated
= 0;
24 PUCHAR x86BiosMemoryMapping
;
29 DbgDumpPage(PUCHAR MemBuffer
, USHORT Segment
)
33 for (y
= 0; y
< 0x100; y
++)
35 for (x
= 0; x
< 0x10; x
++)
37 Offset
= Segment
* 16 + y
* 16 + x
;
38 DbgPrint("%02x ", MemBuffer
[Offset
]);
46 HalInitializeBios(ULONG Unknown
, PLOADER_PARAMETER_BLOCK LoaderBlock
)
50 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
;
51 PLIST_ENTRY ListEntry
;
54 /* Allocate an MDL for 1MB */
55 Mdl
= IoAllocateMdl(NULL
, 0x100000, FALSE
, FALSE
, NULL
);
61 /* Get pointer to the pfn array */
62 PfnArray
= MmGetMdlPfnArray(Mdl
);
64 /* Fill the array with low memory PFNs */
65 for (Pfn
= 0; Pfn
< 0x100; Pfn
++)
70 /* Loop the memory descriptors */
71 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Flink
;
72 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
73 ListEntry
= ListEntry
->Flink
)
75 /* Get the memory descriptor */
76 Descriptor
= CONTAINING_RECORD(ListEntry
,
77 MEMORY_ALLOCATION_DESCRIPTOR
,
80 /* Check if the memory is in the low range */
81 if (Descriptor
->BasePage
< 0x100)
83 /* Check if the memory type is firmware */
84 if (Descriptor
->MemoryType
!= LoaderFirmwarePermanent
&&
85 Descriptor
->MemoryType
!= LoaderSpecialMemory
)
87 /* It's something else, so don't use it! */
88 Last
= min(Descriptor
->BasePage
+ Descriptor
->PageCount
, 0x100);
89 for (Pfn
= Descriptor
->BasePage
; Pfn
< Last
; Pfn
++)
91 /* Set each page to the default page */
92 PfnArray
[Pfn
] = DEFAULT_PAGE
;
98 Mdl
->MdlFlags
= MDL_PAGES_LOCKED
;
100 /* Map the MDL to system space */
101 x86BiosMemoryMapping
= MmGetSystemAddressForMdlSafe(Mdl
, HighPagePriority
);
102 ASSERT(x86BiosMemoryMapping
);
104 DPRINT1("memory: %p, %p\n", *(PVOID
*)x86BiosMemoryMapping
, *(PVOID
*)(x86BiosMemoryMapping
+ 8));
105 //DbgDumpPage(x86BiosMemoryMapping, 0xc351);
107 x86BiosIsInitialized
= TRUE
;
109 HalpBiosDisplayReset();
114 x86BiosAllocateBuffer(
119 /* Check if the system is initialized and the buffer is large enough */
120 if (!x86BiosIsInitialized
|| *Size
> PAGE_SIZE
)
122 /* Something was wrong, fail! */
123 return STATUS_INSUFFICIENT_RESOURCES
;
126 /* Check if the buffer is already allocated */
127 if (InterlockedBitTestAndSet(&x86BiosBufferIsAllocated
, 0))
129 /* Buffer was already allocated, fail */
130 return STATUS_INSUFFICIENT_RESOURCES
;
133 /* The buffer is sufficient, return hardcoded address and size */
138 return STATUS_SUCCESS
;;
147 /* Check if the system is initialized and if the address matches */
148 if (!x86BiosIsInitialized
|| Segment
!= 0x2000 || Offset
!= 0)
150 /* Something was wrong, fail */
151 return STATUS_INVALID_PARAMETER
;
154 /* Check if the buffer was allocated */
155 if (!InterlockedBitTestAndReset(&x86BiosBufferIsAllocated
, 0))
157 /* It was not, fail */
158 return STATUS_INVALID_PARAMETER
;
161 /* Buffer is freed, nothing more to do */
162 return STATUS_SUCCESS
;;
175 /* Calculate the physical address */
176 Address
= (Segment
<< 4) + Offset
;
178 /* Check if it's valid */
179 if (!x86BiosIsInitialized
|| Address
+ Size
> 0x100000)
182 return STATUS_INVALID_PARAMETER
;
185 /* Copy the memory to the buffer */
186 RtlCopyMemory(Buffer
, x86BiosMemoryMapping
+ Address
, Size
);
189 return STATUS_SUCCESS
;
202 /* Calculate the physical address */
203 Address
= (Segment
<< 4) + Offset
;
205 /* Check if it's valid */
206 if (!x86BiosIsInitialized
|| Address
+ Size
> 0x100000)
209 return STATUS_INVALID_PARAMETER
;
212 /* Copy the memory from the buffer */
213 RtlCopyMemory(x86BiosMemoryMapping
+ Address
, Buffer
, Size
);
216 return STATUS_SUCCESS
;
223 ULONG InterruptNumber
,
224 X86_BIOS_REGISTERS
*Registers
)
226 X86_VM_STATE VmState
;
233 /* Zero the VmState */
234 RtlZeroMemory(&VmState
, sizeof(VmState
));
236 /* Copy the registers */
237 VmState
.BiosRegisters
= *Registers
;
239 /* Set the physical memory buffer */
240 VmState
.MemBuffer
= x86BiosMemoryMapping
;
243 VmState
.Registers
.Eflags
.Long
= 0; // FIXME
246 VmState
.Registers
.SegSs
= 0; // FIXME
247 VmState
.Registers
.Sp
= 0x2000 - 2; // FIXME
249 /* Initialize IP from the interrupt vector table */
250 InterrupTable
= (PVOID
)x86BiosMemoryMapping
;
251 VmState
.Registers
.SegCs
= InterrupTable
[InterruptNumber
].SegCs
;
252 VmState
.Registers
.Eip
= InterrupTable
[InterruptNumber
].Ip
;
254 /* Make the function return on IRET */
255 VmState
.Flags
.ReturnOnIret
= 1;
257 /* Call the x86 emulator */
258 x86Emulator(&VmState
);
260 /* Copy registers back to caller */
261 *Registers
= VmState
.BiosRegisters
;
269 HalpBiosDisplayReset(VOID
)
272 X86_BIOS_REGISTERS Registers
;
275 /* Save flags and disable interrupts */
276 OldEflags
= __readeflags();
279 /* Set AH = 0 (Set video mode), AL = 0x12 (640x480x16 vga) */
280 Registers
.Eax
= 0x12;
283 x86BiosCall(0x10, &Registers
);
285 // FIXME: check result
287 /* Restore previous flags */
288 __writeeflags(OldEflags
);