ReactOS 0.4.15-dev-6057-gd708c79
x86bios.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS HAL
3 * LICENSE: GPL, See COPYING in the top level directory
4 * FILE: hal/halx86/amd64/x86bios.c
5 * PURPOSE:
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <hal.h>
12//#define NDEBUG
13#include <debug.h>
14
15#include <fast486.h>
16
17/* GLOBALS *******************************************************************/
18
19/* This page serves as fallback for pages used by Mm */
21
25
26/* This the physical address of the bios buffer */
28
29VOID
32{
33 ULONG x, y, Offset;
34
35 for (y = 0; y < 0x100; y++)
36 {
37 for (x = 0; x < 0x10; x++)
38 {
39 Offset = Segment * 16 + y * 16 + x;
40 DbgPrint("%02x ", MemBuffer[Offset]);
41 }
42 DbgPrint("\n");
43 }
44}
45
46VOID
49 _In_ ULONG Phase,
50 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
51{
52 PPFN_NUMBER PfnArray;
53 PFN_NUMBER Pfn, Last;
55 PLIST_ENTRY ListEntry;
56 PMDL Mdl;
58
59 if (Phase == 0)
60 {
61 /* Allocate one page for a fallback mapping */
63 0x100000,
64 1,
65 FALSE);
66 if (PhysicalAddress == 0)
67 {
69 }
70
73
74 /* Allocate a page for the buffer allocation */
76 0x100000,
77 1,
78 FALSE);
79 if (x86BiosBufferPhysical == 0)
80 {
82 }
83 }
84 else
85 {
86
87 /* Allocate an MDL for 1MB */
88 Mdl = IoAllocateMdl(NULL, 0x100000, FALSE, FALSE, NULL);
89 if (!Mdl)
90 {
92 }
93
94 /* Get pointer to the pfn array */
95 PfnArray = MmGetMdlPfnArray(Mdl);
96
97 /* Fill the array with the fallback page */
98 for (Pfn = 0; Pfn < 0x100; Pfn++)
99 {
100 PfnArray[Pfn] = x86BiosFallbackPfn;
101 }
102
103 /* Loop the memory descriptors */
104 for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
105 ListEntry != &LoaderBlock->MemoryDescriptorListHead;
106 ListEntry = ListEntry->Flink)
107 {
108 /* Get the memory descriptor */
109 Descriptor = CONTAINING_RECORD(ListEntry,
111 ListEntry);
112
113 /* Check if the memory is in the low 1 MB range */
114 if (Descriptor->BasePage < 0x100)
115 {
116 /* Check if the memory type is firmware */
117 if ((Descriptor->MemoryType == LoaderFirmwarePermanent) ||
118 (Descriptor->MemoryType == LoaderSpecialMemory))
119 {
120 /* It's firmware, so map it! */
121 Last = min(Descriptor->BasePage + Descriptor->PageCount, 0x100);
122 for (Pfn = Descriptor->BasePage; Pfn < Last; Pfn++)
123 {
124 /* Set each physical page in the MDL */
125 PfnArray[Pfn] = Pfn;
126 }
127 }
128 }
129 }
130
131 /* Map this page proper, too */
133 PfnArray[Pfn] = Pfn;
134
135 Mdl->MdlFlags = MDL_PAGES_LOCKED;
136
137 /* Map the MDL to system space */
140
141 DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping, *(PVOID*)(x86BiosMemoryMapping + 8));
142 //DbgDumpPage(x86BiosMemoryMapping, 0xc351);
143
145
147 }
148}
149
151NTAPI
153 _In_ ULONG *Size,
156{
157 /* Check if the system is initialized and the buffer is large enough */
159 {
160 /* Something was wrong, fail! */
162 }
163
164 /* Check if the buffer is already allocated */
166 {
167 /* Buffer was already allocated, fail */
169 }
170
171 /* The buffer is sufficient, return hardcoded address and size */
172 *Size = PAGE_SIZE;
174 *Offset = 0;
175
176 return STATUS_SUCCESS;
177}
178
180NTAPI
184{
185 /* Check if the system is initialized and if the address matches */
186 if (!x86BiosIsInitialized || (Segment != 0x2000) || (Offset != 0))
187 {
188 /* Something was wrong, fail */
190 }
191
192 /* Check if the buffer was allocated */
194 {
195 /* It was not, fail */
197 }
198
199 /* Buffer is freed, nothing more to do */
200 return STATUS_SUCCESS;
201}
202
204NTAPI
210{
212
213 /* Calculate the physical address */
214 Address = (Segment << 4) + Offset;
215
216 /* Check if it's valid */
217 if (!x86BiosIsInitialized || ((Address + Size) > 0x100000))
218 {
219 /* Invalid */
221 }
222
223 /* Copy the memory to the buffer */
225
226 /* Return success */
227 return STATUS_SUCCESS;
228}
229
231NTAPI
237{
239
240 /* Calculate the physical address */
241 Address = (Segment << 4) + Offset;
242
243 /* Check if it's valid */
244 if (!x86BiosIsInitialized || ((Address + Size) > 0x100000))
245 {
246 /* Invalid */
248 }
249
250 /* Copy the memory from the buffer */
252
253 /* Return success */
254 return STATUS_SUCCESS;
255}
256
257static
258VOID
261 PFAST486_STATE State,
264 ULONG Size)
265{
266 /* Validate the address range */
267 if (((ULONG64)Address + Size) < 0x100000)
268 {
270 }
271 else
272 {
273 RtlFillMemory(Buffer, Size, 0xCC);
274 DPRINT1("x86MemRead: invalid read at 0x%lx (size 0x%lx)", Address, Size);
275 }
276}
277
278static
279VOID
282 PFAST486_STATE State,
285 ULONG Size)
286{
287 /* Validate the address range */
288 if (((ULONG64)Address + Size) < 0x100000)
289 {
291 }
292 else
293 {
294 DPRINT1("x86MemWrite: invalid write at 0x%lx (size 0x%lx)", Address, Size);
295 }
296}
297
298static
301 USHORT Port,
302 UCHAR Size,
303 BOOLEAN IsWrite)
304{
305 switch (Port)
306 {
307 // VGA: https://wiki.osdev.org/VGA_Hardware#Port_0x3C0
308 case 0x3C0: return (Size == 1) && IsWrite;
309 case 0x3C1: return (Size == 1) && !IsWrite;
310 case 0x3C2: return (Size == 1) && IsWrite;
311 case 0x3C4: return IsWrite;
312 case 0x3C5: return (Size <= 2);
313 case 0x3C7: return (Size == 1) && IsWrite;
314 case 0x3CC: return (Size == 1) && !IsWrite;
315 case 0x3CE: return IsWrite;
316 case 0x3CF: return (Size <= 2);
317 case 0x3D4: return IsWrite;
318 case 0x3D5: return (Size <= 2);
319 case 0x3C6: return (Size == 1);
320 case 0x3C8: return (Size == 1) && IsWrite;
321 case 0x3C9: return (Size == 1);
322 case 0x3DA: return (Size == 1) && !IsWrite;
323
324 // OVMF debug messages used by VBox / QEMU
325 // https://www.virtualbox.org/svn/vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/README
326 case 0x402: return (Size == 1) && IsWrite;
327
328 // BOCHS VBE: https://forum.osdev.org/viewtopic.php?f=1&t=14639
329 case 0x1CE: return (Size == 1) && IsWrite;
330 case 0x1CF: return (Size == 1);
331
332 // CHECKME!
333 case 0x3B6: return (Size <= 2);
334 }
335
336 /* Allow but report unknown ports, we trust the BIOS for now */
337 DPRINT1("Unknown port 0x%x, size %d, write %d\n", Port, Size, IsWrite);
338 return TRUE;
339}
340
341static
342VOID
345 PFAST486_STATE State,
346 USHORT Port,
348 ULONG DataCount,
350{
351 /* Validate the port */
353 {
354 DPRINT1("Invalid IO port read access (port: 0x%x, count: 0x%x)\n", Port, DataSize);
355 }
356
357 switch (DataSize)
358 {
359 case 1: READ_PORT_BUFFER_UCHAR((PUCHAR)(ULONG_PTR)Port, Buffer, DataCount); return;
360 case 2: READ_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)Port, Buffer, DataCount); return;
361 case 4: READ_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)Port, Buffer, DataCount); return;
362 }
363}
364
365static
366VOID
369 PFAST486_STATE State,
370 USHORT Port,
372 ULONG DataCount,
374{
375 /* Validate the port */
377 {
378 DPRINT1("Invalid IO port write access (port: 0x%x, count: 0x%x)\n", Port, DataSize);
379 }
380
381 switch (DataSize)
382 {
383 case 1: WRITE_PORT_BUFFER_UCHAR((PUCHAR)(ULONG_PTR)Port, Buffer, DataCount); return;
384 case 2: WRITE_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)Port, Buffer, DataCount); return;
385 case 4: WRITE_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)Port, Buffer, DataCount); return;
386 }
387}
388
389static
390VOID
393 PFAST486_STATE State,
394 UCHAR BopCode)
395{
396 ASSERT(FALSE);
397}
398
399static
400UCHAR
403 PFAST486_STATE State)
404{
405 ASSERT(FALSE);
406 return 0;
407}
408
410NTAPI
412 _In_ ULONG InterruptNumber,
413 _Inout_ PX86_BIOS_REGISTERS Registers)
414{
415 const ULONG StackBase = 0x2000;
416 FAST486_STATE EmulatorContext;
417 ULONG FlatIp;
418 PUCHAR InstructionPointer;
419
420 /* Initialize the emulator context */
424 x86IoRead,
426 x86BOP,
427 x86IntAck,
428 NULL, // FpuCallback,
429 NULL); // Tlb
430
431 /* Copy the registers */
432 EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long = Registers->Eax;
433 EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long = Registers->Ebx;
434 EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long = Registers->Ecx;
435 EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long = Registers->Edx;
436 EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long = Registers->Esi;
437 EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long = Registers->Edi;
438 EmulatorContext.SegmentRegs[FAST486_REG_DS].Selector = Registers->SegDs;
439 EmulatorContext.SegmentRegs[FAST486_REG_ES].Selector = Registers->SegEs;
440
441 /* Set Eflags */
442 EmulatorContext.Flags.Long = 0;
443 EmulatorContext.Flags.AlwaysSet = 1;
444 EmulatorContext.Flags.If = 1;
445
446 /* Set up the INT stub */
447 FlatIp = StackBase - 4;
448 InstructionPointer = x86BiosMemoryMapping + FlatIp;
449 InstructionPointer[0] = 0xCD; // INT instruction
450 InstructionPointer[1] = (UCHAR)InterruptNumber;
451 InstructionPointer[2] = 0x90; // NOP. We will stop at this address.
452
453 /* Set the stack pointer */
454 Fast486SetStack(&EmulatorContext, 0, StackBase - 8);
455
456 /* Start execution at the INT stub */
457 Fast486ExecuteAt(&EmulatorContext, 0x00, FlatIp);
458
459 while (TRUE)
460 {
461 /* Get the current flat IP */
462 FlatIp = (EmulatorContext.SegmentRegs[FAST486_REG_CS].Selector << 4) +
463 EmulatorContext.InstPtr.Long;
464
465 /* Make sure we haven't left the allowed memory range */
466 if (FlatIp >= 0x100000)
467 {
468 DPRINT1("x86BiosCall: invalid IP (0x%lx) during BIOS execution", FlatIp);
469 return FALSE;
470 }
471
472 /* Check if we returned from our int stub */
473 if (FlatIp == (StackBase - 2))
474 {
475 /* We are done! */
476 break;
477 }
478
479 /* Emulate one instruction */
481 }
482
483 /* Copy the registers back */
484 Registers->Eax = EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long;
485 Registers->Ebx = EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long;
486 Registers->Ecx = EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long;
487 Registers->Edx = EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long;
488 Registers->Esi = EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long;
489 Registers->Edi = EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long;
490 Registers->SegDs = EmulatorContext.SegmentRegs[FAST486_REG_DS].Selector;
491 Registers->SegEs = EmulatorContext.SegmentRegs[FAST486_REG_ES].Selector;
492
493 return TRUE;
494}
495
497NTAPI
499{
500#if 0
501 X86_BIOS_REGISTERS Registers;
502 ULONG OldEflags;
503
504 /* Save flags and disable interrupts */
505 OldEflags = __readeflags();
506 _disable();
507
508 /* Set AH = 0 (Set video mode), AL = 0x12 (640x480x16 vga) */
509 Registers.Eax = 0x12;
510
511 /* Call INT 0x10 */
512 x86BiosCall(0x10, &Registers);
513
514 // FIXME: check result
515
516 /* Restore previous flags */
517 __writeeflags(OldEflags);
518 return TRUE;
519#else
520 /* This x64 HAL does NOT currently handle display reset (TODO) */
521 return FALSE;
522#endif
523}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define PAGE_SIZE
Definition: env_spec_w32.h:49
VOID NTAPI Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset)
Definition: fast486.c:227
VOID NTAPI Fast486Initialize(PFAST486_STATE State, FAST486_MEM_READ_PROC MemReadCallback, FAST486_MEM_WRITE_PROC MemWriteCallback, FAST486_IO_READ_PROC IoReadCallback, FAST486_IO_WRITE_PROC IoWriteCallback, FAST486_BOP_PROC BopCallback, FAST486_INT_ACK_PROC IntAckCallback, FAST486_FPU_PROC FpuCallback, PULONG Tlb)
Definition: fast486.c:103
VOID NTAPI Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset)
Definition: fast486.c:212
#define IoAllocateMdl
Definition: fxmdl.h:88
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
VOID NTAPI WRITE_PORT_BUFFER_UCHAR(IN PUCHAR Port, IN PUCHAR Buffer, IN ULONG Count)
Definition: portio.c:77
VOID NTAPI WRITE_PORT_BUFFER_ULONG(IN PULONG Port, IN PULONG Buffer, IN ULONG Count)
Definition: portio.c:97
VOID NTAPI WRITE_PORT_BUFFER_USHORT(IN PUSHORT Port, IN PUSHORT Buffer, IN ULONG Count)
Definition: portio.c:87
VOID NTAPI READ_PORT_BUFFER_UCHAR(IN PUCHAR Port, OUT PUCHAR Buffer, IN ULONG Count)
Definition: portio.c:26
VOID NTAPI READ_PORT_BUFFER_USHORT(IN PUSHORT Port, OUT PUSHORT Buffer, IN ULONG Count)
Definition: portio.c:36
VOID NTAPI READ_PORT_BUFFER_ULONG(IN PULONG Port, OUT PULONG Buffer, IN ULONG Count)
Definition: portio.c:46
#define DbgPrint
Definition: hal.h:12
ULONG64 NTAPI HalpAllocPhysicalMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN ULONG64 MaxAddress, IN PFN_NUMBER PageCount, IN BOOLEAN Aligned)
Definition: memory.c:29
CPPORT Port[4]
Definition: headless.c:35
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define InterlockedBitTestAndSet
Definition: interlocked.h:30
#define InterlockedBitTestAndReset
Definition: interlocked.h:35
void __cdecl _disable(void)
Definition: intrin_arm.h:365
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1669
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
@ HighPagePriority
Definition: imports.h:57
#define min(a, b)
Definition: monoChain.cc:55
#define _In_reads_bytes_(size)
Definition: ms_sal.h:321
#define _Inout_
Definition: ms_sal.h:378
#define _Out_writes_bytes_(size)
Definition: ms_sal.h:350
#define _In_
Definition: ms_sal.h:308
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
#define FASTCALL
Definition: nt_native.h:50
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68
@ LoaderFirmwarePermanent
Definition: arc.h:133
@ LoaderSpecialMemory
Definition: arc.h:149
ULONG * PPFN_NUMBER
Definition: ke.h:9
ULONG PFN_NUMBER
Definition: ke.h:9
VOID NTAPI Fast486StepInto(PFAST486_STATE State)
Definition: debug.c:248
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
FAST486_STATE EmulatorContext
Definition: cpu.c:39
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
LONG x86BiosBufferIsAllocated
Definition: x86bios.c:23
static VOID FASTCALL x86IoRead(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
Definition: x86bios.c:344
NTSTATUS NTAPI x86BiosFreeBuffer(_In_ USHORT Segment, _In_ USHORT Offset)
Definition: x86bios.c:181
NTSTATUS NTAPI x86BiosReadMemory(_In_ USHORT Segment, _In_ USHORT Offset, _Out_writes_bytes_(Size) PVOID Buffer, _In_ ULONG Size)
Definition: x86bios.c:205
VOID NTAPI DbgDumpPage(PUCHAR MemBuffer, USHORT Segment)
Definition: x86bios.c:31
BOOLEAN NTAPI x86BiosCall(_In_ ULONG InterruptNumber, _Inout_ PX86_BIOS_REGISTERS Registers)
Definition: x86bios.c:411
NTSTATUS NTAPI x86BiosWriteMemory(_In_ USHORT Segment, _In_ USHORT Offset, _In_reads_bytes_(Size) PVOID Buffer, _In_ ULONG Size)
Definition: x86bios.c:232
VOID NTAPI HalInitializeBios(_In_ ULONG Phase, _In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: x86bios.c:48
static VOID FASTCALL x86MemWrite(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
Definition: x86bios.c:281
BOOLEAN NTAPI HalpBiosDisplayReset(VOID)
Definition: x86bios.c:498
static VOID FASTCALL x86MemRead(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
Definition: x86bios.c:260
BOOLEAN x86BiosIsInitialized
Definition: x86bios.c:22
PUCHAR x86BiosMemoryMapping
Definition: x86bios.c:24
static UCHAR FASTCALL x86IntAck(PFAST486_STATE State)
Definition: x86bios.c:402
ULONG64 x86BiosBufferPhysical
Definition: x86bios.c:27
static VOID FASTCALL x86IoWrite(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
Definition: x86bios.c:368
static BOOLEAN ValidatePort(USHORT Port, UCHAR Size, BOOLEAN IsWrite)
Definition: x86bios.c:300
static VOID FASTCALL x86BOP(PFAST486_STATE State, UCHAR BopCode)
Definition: x86bios.c:392
PFN_NUMBER x86BiosFallbackPfn
Definition: x86bios.c:20
NTSTATUS NTAPI x86BiosAllocateBuffer(_In_ ULONG *Size, _In_ USHORT *Segment, _In_ USHORT *Offset)
Definition: x86bios.c:152
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define MmGetMdlPfnArray(_Mdl)
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
unsigned char UCHAR
Definition: xmlstorage.h:181