ReactOS  0.4.14-dev-98-gb0d4763
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 /* This page serves as fallback for pages used by Mm */
18 #define DEFAULT_PAGE 0x21
19 
20 /* GLOBALS *******************************************************************/
21 
25 
26 
27 VOID
28 NTAPI
30 {
31  ULONG x, y, Offset;
32 
33  for (y = 0; y < 0x100; y++)
34  {
35  for (x = 0; x < 0x10; x++)
36  {
37  Offset = Segment * 16 + y * 16 + x;
38  DbgPrint("%02x ", MemBuffer[Offset]);
39  }
40  DbgPrint("\n");
41  }
42 }
43 
44 VOID
45 NTAPI
48  _In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
49 {
50  PPFN_NUMBER PfnArray;
51  PFN_NUMBER Pfn, Last;
53  PLIST_ENTRY ListEntry;
54  PMDL Mdl;
55 
56  /* Allocate an MDL for 1MB */
57  Mdl = IoAllocateMdl(NULL, 0x100000, FALSE, FALSE, NULL);
58  if (!Mdl)
59  {
60  ASSERT(FALSE);
61  }
62 
63  /* Get pointer to the pfn array */
64  PfnArray = MmGetMdlPfnArray(Mdl);
65 
66  /* Fill the array with low memory PFNs */
67  for (Pfn = 0; Pfn < 0x100; Pfn++)
68  {
69  PfnArray[Pfn] = Pfn;
70  }
71 
72  /* Loop the memory descriptors */
73  for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
74  ListEntry != &LoaderBlock->MemoryDescriptorListHead;
75  ListEntry = ListEntry->Flink)
76  {
77  /* Get the memory descriptor */
78  Descriptor = CONTAINING_RECORD(ListEntry,
80  ListEntry);
81 
82  /* Check if the memory is in the low range */
83  if (Descriptor->BasePage < 0x100)
84  {
85  /* Check if the memory type is firmware */
86  if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
87  Descriptor->MemoryType != LoaderSpecialMemory)
88  {
89  /* It's something else, so don't use it! */
90  Last = min(Descriptor->BasePage + Descriptor->PageCount, 0x100);
91  for (Pfn = Descriptor->BasePage; Pfn < Last; Pfn++)
92  {
93  /* Set each page to the default page */
94  PfnArray[Pfn] = DEFAULT_PAGE;
95  }
96  }
97  }
98  }
99 
100  Mdl->MdlFlags = MDL_PAGES_LOCKED;
101 
102  /* Map the MDL to system space */
105 
106  DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping, *(PVOID*)(x86BiosMemoryMapping + 8));
107  //DbgDumpPage(x86BiosMemoryMapping, 0xc351);
108 
110 
112 }
113 
114 NTSTATUS
115 NTAPI
117  _In_ ULONG *Size,
119  _In_ USHORT *Offset)
120 {
121  /* Check if the system is initialized and the buffer is large enough */
122  if (!x86BiosIsInitialized || (*Size > PAGE_SIZE))
123  {
124  /* Something was wrong, fail! */
126  }
127 
128  /* Check if the buffer is already allocated */
130  {
131  /* Buffer was already allocated, fail */
133  }
134 
135  /* The buffer is sufficient, return hardcoded address and size */
136  *Size = PAGE_SIZE;
137  *Segment = 0x2000;
138  *Offset = 0;
139 
140  return STATUS_SUCCESS;
141 }
142 
143 NTSTATUS
144 NTAPI
148 {
149  /* Check if the system is initialized and if the address matches */
150  if (!x86BiosIsInitialized || (Segment != 0x2000) || (Offset != 0))
151  {
152  /* Something was wrong, fail */
154  }
155 
156  /* Check if the buffer was allocated */
158  {
159  /* It was not, fail */
161  }
162 
163  /* Buffer is freed, nothing more to do */
164  return STATUS_SUCCESS;
165 }
166 
167 NTSTATUS
168 NTAPI
173  _In_ ULONG Size)
174 {
176 
177  /* Calculate the physical address */
178  Address = (Segment << 4) + Offset;
179 
180  /* Check if it's valid */
181  if (!x86BiosIsInitialized || ((Address + Size) > 0x100000))
182  {
183  /* Invalid */
185  }
186 
187  /* Copy the memory to the buffer */
189 
190  /* Return success */
191  return STATUS_SUCCESS;
192 }
193 
194 NTSTATUS
195 NTAPI
200  _In_ ULONG Size)
201 {
203 
204  /* Calculate the physical address */
205  Address = (Segment << 4) + Offset;
206 
207  /* Check if it's valid */
208  if (!x86BiosIsInitialized || ((Address + Size) > 0x100000))
209  {
210  /* Invalid */
212  }
213 
214  /* Copy the memory from the buffer */
216 
217  /* Return success */
218  return STATUS_SUCCESS;
219 }
220 
221 static
222 VOID
223 FASTCALL
225  PFAST486_STATE State,
226  ULONG Address,
227  PVOID Buffer,
228  ULONG Size)
229 {
230  /* Validate the address range */
231  if (((ULONG64)Address + Size) < 0x100000)
232  {
234  }
235  else
236  {
237  RtlFillMemory(Buffer, Size, 0xCC);
238  DPRINT1("x86MemRead: invalid read at 0x%lx (size 0x%lx)", Address, Size);
239  }
240 }
241 
242 static
243 VOID
244 FASTCALL
246  PFAST486_STATE State,
247  ULONG Address,
248  PVOID Buffer,
249  ULONG Size)
250 {
251  /* Validate the address range */
252  if (((ULONG64)Address + Size) < 0x100000)
253  {
255  }
256  else
257  {
258  DPRINT1("x86MemWrite: invalid write at 0x%lx (size 0x%lx)", Address, Size);
259  }
260 }
261 
262 static
263 BOOLEAN
265  USHORT Port,
266  UCHAR Size,
267  BOOLEAN IsWrite)
268 {
269  switch (Port)
270  {
271  // VGA: https://wiki.osdev.org/VGA_Hardware#Port_0x3C0
272  case 0x3C0: return (Size == 1) && IsWrite;
273  case 0x3C1: return (Size == 1) && !IsWrite;
274  case 0x3C2: return (Size == 1) && IsWrite;
275  case 0x3C4: return IsWrite;
276  case 0x3C5: return (Size <= 2);
277  case 0x3C7: return (Size == 1) && IsWrite;
278  case 0x3CC: return (Size == 1) && !IsWrite;
279  case 0x3CE: return IsWrite;
280  case 0x3CF: return (Size <= 2);
281  case 0x3D4: return IsWrite;
282  case 0x3D5: return (Size <= 2);
283  case 0x3C6: return (Size == 1);
284  case 0x3C8: return (Size == 1) && IsWrite;
285  case 0x3C9: return (Size == 1);
286  case 0x3DA: return (Size == 1) && !IsWrite;
287 
288  // CHECKME!
289  case 0x1CE: return (Size == 1) && IsWrite;
290  case 0x1CF: return (Size == 1);
291  case 0x3B6: return (Size <= 2);
292  }
293 
294  return FALSE;
295 }
296 
297 static
298 VOID
299 FASTCALL
301  PFAST486_STATE State,
302  USHORT Port,
303  PVOID Buffer,
304  ULONG DataCount,
305  UCHAR DataSize)
306 {
307  /* Validate the port */
309  {
310  DPRINT1("Invalid IO port read access (port: 0x%x, count: 0x%x)\n", Port, DataSize);
311  }
312 
313  switch (DataSize)
314  {
315  case 1: READ_PORT_BUFFER_UCHAR((PUCHAR)(ULONG_PTR)Port, Buffer, DataCount); return;
316  case 2: READ_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)Port, Buffer, DataCount); return;
317  case 4: READ_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)Port, Buffer, DataCount); return;
318  }
319 }
320 
321 static
322 VOID
323 FASTCALL
325  PFAST486_STATE State,
326  USHORT Port,
327  PVOID Buffer,
328  ULONG DataCount,
329  UCHAR DataSize)
330 {
331  /* Validate the port */
332  if (!ValidatePort(Port, DataSize, TRUE))
333  {
334  DPRINT1("Invalid IO port write access (port: 0x%x, count: 0x%x)\n", Port, DataSize);
335  }
336 
337  switch (DataSize)
338  {
339  case 1: WRITE_PORT_BUFFER_UCHAR((PUCHAR)(ULONG_PTR)Port, Buffer, DataCount); return;
340  case 2: WRITE_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)Port, Buffer, DataCount); return;
341  case 4: WRITE_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)Port, Buffer, DataCount); return;
342  }
343 }
344 
345 static
346 VOID
347 FASTCALL
349  PFAST486_STATE State,
350  UCHAR BopCode)
351 {
352  ASSERT(FALSE);
353 }
354 
355 static
356 UCHAR
357 FASTCALL
359  PFAST486_STATE State)
360 {
361  ASSERT(FALSE);
362  return 0;
363 }
364 
365 BOOLEAN
366 NTAPI
368  _In_ ULONG InterruptNumber,
369  _Inout_ PX86_BIOS_REGISTERS Registers)
370 {
371  FAST486_STATE EmulatorContext;
372  struct
373  {
374  USHORT Ip;
375  USHORT SegCs;
376  } *Ivt;
377  ULONG FlatIp;
378  PUCHAR InstructionPointer;
379 
380  /* Initialize the emulator context */
382  x86MemRead,
383  x86MemWrite,
384  x86IoRead,
385  x86IoWrite,
386  x86BOP,
387  x86IntAck,
388  NULL, // FpuCallback,
389  NULL); // Tlb
390 
391 //RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop);
392 
393  /* Copy the registers */
394  EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long = Registers->Eax;
395  EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long = Registers->Ebx;
396  EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long = Registers->Ecx;
397  EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long = Registers->Edx;
398  EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long = Registers->Esi;
399  EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long = Registers->Edi;
400  EmulatorContext.SegmentRegs[FAST486_REG_DS].Selector = Registers->SegDs;
401  EmulatorContext.SegmentRegs[FAST486_REG_ES].Selector = Registers->SegEs;
402 
403  /* Set Eflags */
404  EmulatorContext.Flags.Long = 0;
405  EmulatorContext.Flags.AlwaysSet = 1;
406  EmulatorContext.Flags.If = 1;
407 
408  /* Set the stack pointer */
409  Fast486SetStack(&EmulatorContext, 0, 0x2000 - 2); // FIXME
410 
411  /* Set CS:EIP from the IVT entry */
414  Ivt[InterruptNumber].SegCs,
415  Ivt[InterruptNumber].Ip);
416 
417  while (TRUE)
418  {
419  /* Step one instruction */
421 
422  /* Check for iret */
423  FlatIp = (EmulatorContext.SegmentRegs[FAST486_REG_CS].Selector << 4) +
424  EmulatorContext.InstPtr.Long;
425  if (FlatIp >= 0x100000)
426  {
427  DPRINT1("x86BiosCall: invalid IP (0x%lx) during BIOS execution", FlatIp);
428  return FALSE;
429  }
430 
431  /* Read the next instruction and check if it's IRET */
432  InstructionPointer = x86BiosMemoryMapping + FlatIp;
433  if (*InstructionPointer == 0xCF)
434  {
435  /* We are done! */
436  break;
437  }
438  }
439 
440  /* Copy the registers back */
441  Registers->Eax = EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long;
442  Registers->Ebx = EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long;
443  Registers->Ecx = EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long;
444  Registers->Edx = EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long;
445  Registers->Esi = EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long;
446  Registers->Edi = EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long;
447  Registers->SegDs = EmulatorContext.SegmentRegs[FAST486_REG_DS].Selector;
448  Registers->SegEs = EmulatorContext.SegmentRegs[FAST486_REG_ES].Selector;
449 
450  return TRUE;
451 }
452 
453 BOOLEAN
454 NTAPI
456 {
457 #if 0
458  X86_BIOS_REGISTERS Registers;
459  ULONG OldEflags;
460 
461  /* Save flags and disable interrupts */
462  OldEflags = __readeflags();
463  _disable();
464 
465  /* Set AH = 0 (Set video mode), AL = 0x12 (640x480x16 vga) */
466  Registers.Eax = 0x12;
467 
468  /* Call INT 0x10 */
469  x86BiosCall(0x10, &Registers);
470 
471  // FIXME: check result
472 
473  /* Restore previous flags */
474  __writeeflags(OldEflags);
475 #endif
476  return TRUE;
477 }
478 
CPPORT Port[4]
Definition: headless.c:34
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define MmGetMdlPfnArray(_Mdl)
#define DbgPrint
Definition: loader.c:25
VOID NTAPI WRITE_PORT_BUFFER_UCHAR(IN PUCHAR Port, IN PUCHAR Buffer, IN ULONG Count)
Definition: portio.c:77
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI READ_PORT_BUFFER_UCHAR(IN PUCHAR Port, OUT PUCHAR Buffer, IN ULONG Count)
Definition: portio.c:26
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
VOID NTAPI Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset)
Definition: fast486.c:227
BOOLEAN NTAPI HalpBiosDisplayReset(VOID)
Definition: x86bios.c:455
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define FASTCALL
Definition: nt_native.h:50
#define DEFAULT_PAGE
Definition: x86bios.c:18
uint32_t ULONG_PTR
Definition: typedefs.h:63
ULONG * PPFN_NUMBER
Definition: ke.h:8
NTSTATUS NTAPI x86BiosFreeBuffer(_In_ USHORT Segment, _In_ USHORT Offset)
Definition: x86bios.c:145
ULONG PFN_NUMBER
Definition: ke.h:8
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1555
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
static VOID FASTCALL x86IoRead(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
Definition: x86bios.c:300
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
static VOID FASTCALL x86MemRead(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
Definition: x86bios.c:224
long LONG
Definition: pedump.c:60
NTSTATUS NTAPI x86BiosAllocateBuffer(_In_ ULONG *Size, _In_ USHORT *Segment, _In_ USHORT *Offset)
Definition: x86bios.c:116
#define InterlockedBitTestAndReset
Definition: interlocked.h:35
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define _Out_writes_bytes_(size)
Definition: no_sal2.h:370
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
NTSTATUS NTAPI x86BiosReadMemory(_In_ USHORT Segment, _In_ USHORT Offset, _Out_writes_bytes_(Size) PVOID Buffer, _In_ ULONG Size)
Definition: x86bios.c:169
static UCHAR FASTCALL x86IntAck(PFAST486_STATE State)
Definition: x86bios.c:358
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:893
#define InterlockedBitTestAndSet
Definition: interlocked.h:30
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID NTAPI Fast486StepInto(PFAST486_STATE State)
Definition: debug.c:248
static VOID FASTCALL x86BOP(PFAST486_STATE State, UCHAR BopCode)
Definition: x86bios.c:348
if(!(yy_init))
Definition: macro.lex.yy.c:714
static VOID FASTCALL x86IoWrite(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
Definition: x86bios.c:324
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define _Inout_
Definition: no_sal2.h:244
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID NTAPI READ_PORT_BUFFER_USHORT(IN PUSHORT Port, OUT PUSHORT Buffer, IN ULONG Count)
Definition: portio.c:36
unsigned __int64 ULONG64
Definition: imports.h:198
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
unsigned char UCHAR
Definition: xmlstorage.h:181
LONG x86BiosBufferIsAllocated
Definition: x86bios.c:23
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1550
VOID NTAPI HalInitializeBios(_In_ ULONG Unknown, _In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: x86bios.c:46
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define _In_reads_bytes_(size)
Definition: no_sal2.h:229
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
static BOOLEAN ValidatePort(USHORT Port, UCHAR Size, BOOLEAN IsWrite)
Definition: x86bios.c:264
#define _In_
Definition: no_sal2.h:204
VOID NTAPI Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset)
Definition: fast486.c:212
PUCHAR x86BiosMemoryMapping
Definition: x86bios.c:24
unsigned short USHORT
Definition: pedump.c:61
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
FAST486_STATE EmulatorContext
Definition: cpu.c:39
#define DPRINT1
Definition: precomp.h:8
void __cdecl _disable(void)
Definition: intrin_arm.h:365
VOID NTAPI READ_PORT_BUFFER_ULONG(IN PULONG Port, OUT PULONG Buffer, IN ULONG Count)
Definition: portio.c:46
unsigned int ULONG
Definition: retypes.h:1
BOOLEAN NTAPI x86BiosCall(_In_ ULONG InterruptNumber, _Inout_ PX86_BIOS_REGISTERS Registers)
Definition: x86bios.c:367
BOOLEAN x86BiosIsInitialized
Definition: x86bios.c:22
VOID NTAPI WRITE_PORT_BUFFER_ULONG(IN PULONG Port, IN PULONG Buffer, IN ULONG Count)
Definition: portio.c:97
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
unsigned short * PUSHORT
Definition: retypes.h:2
VOID NTAPI WRITE_PORT_BUFFER_USHORT(IN PUSHORT Port, IN PUSHORT Buffer, IN ULONG Count)
Definition: portio.c:87
VOID NTAPI DbgDumpPage(PUCHAR MemBuffer, USHORT Segment)
Definition: x86bios.c:29
NTSTATUS NTAPI x86BiosWriteMemory(_In_ USHORT Segment, _In_ USHORT Offset, _In_reads_bytes_(Size) PVOID Buffer, _In_ ULONG Size)
Definition: x86bios.c:196
static VOID FASTCALL x86MemWrite(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
Definition: x86bios.c:245
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966