Author: tkreuzer
Date: Mon Jan 4 23:12:18 2010
New Revision: 44934
URL:
http://svn.reactos.org/svn/reactos?rev=44934&view=rev
Log:
[HAL]
Implement HalInitializeBios, x86BiosAllocateBuffer, x86BiosFreeBuffer, x86BiosReadMemory
and x86BiosWriteMemory
Halfplement x86BiosCall (We don't have the necessary emulator yet)
Modified:
branches/ros-amd64-bringup/reactos/hal/halx86/generic/x86bios.c
Modified: branches/ros-amd64-bringup/reactos/hal/halx86/generic/x86bios.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/hal/h…
==============================================================================
--- branches/ros-amd64-bringup/reactos/hal/halx86/generic/x86bios.c [iso-8859-1]
(original)
+++ branches/ros-amd64-bringup/reactos/hal/halx86/generic/x86bios.c [iso-8859-1] Mon Jan
4 23:12:18 2010
@@ -3,7 +3,7 @@
* LICENSE: See COPYING in the top level directory
* FILE: hal/halamd64/generic/x86bios.c
* PURPOSE:
- * PROGRAMMERS:
+ * PROGRAMMERS: Timo Kreuzer (timo.kreuzer(a)reactos.org)
*/
/* INCLUDES ******************************************************************/
@@ -11,6 +11,78 @@
#include <hal.h>
//#define NDEBUG
#include <debug.h>
+
+/* This page serves as fallback for pages used by Mm */
+#define DEFAULT_PAGE 0x21
+
+/* GLOBALS *******************************************************************/
+
+BOOLEAN x86BiosIsInitialized;
+LONG x86BiosBufferIsAllocated = 0;
+PUCHAR x86BiosMemoryMapping;
+
+VOID
+NTAPI
+HalInitializeBios(ULONG Unknown, PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PPFN_NUMBER PfnArray;
+ PFN_NUMBER Pfn, Last;
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY ListEntry;
+ PMDL Mdl;
+
+ /* Allocate an MDL for 1MB */
+ Mdl = IoAllocateMdl(NULL, 0x100000, FALSE, FALSE, NULL);
+ if (!Mdl)
+ {
+ ASSERT(FALSE);
+ }
+
+ /* Get pointer to the pfn array */
+ PfnArray = MmGetMdlPfnArray(Mdl);
+
+ /* Fill the array with low memory PFNs */
+ for (Pfn = 0; Pfn < 0x100; Pfn++)
+ {
+ PfnArray[Pfn] = Pfn;
+ }
+
+ /* Loop the memory descriptors */
+ for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ ListEntry != &LoaderBlock->MemoryDescriptorListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Get the memory descriptor */
+ Descriptor = CONTAINING_RECORD(ListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Check if the memory is in the low range */
+ if (Descriptor->BasePage < 0x100)
+ {
+ /* Check if the memory type is firmware */
+ if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
+ Descriptor->MemoryType != LoaderFirmwarePermanent)
+ {
+ /* It's something else, so don't use it! */
+ Last = min(Descriptor->BasePage + Descriptor->PageCount, 0x100);
+ for (Pfn = Descriptor->BasePage; Pfn < Last; Pfn++)
+ {
+ /* Set each page to the default page */
+ PfnArray[Pfn] = DEFAULT_PAGE;
+ }
+ }
+ }
+ }
+
+ /* Map the MDL to system space */
+ x86BiosMemoryMapping = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority);
+ ASSERT(x86BiosMemoryMapping);
+
+ DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping,
*(PVOID*)(x86BiosMemoryMapping + 8));
+
+ x86BiosIsInitialized = TRUE;
+}
NTSTATUS
NTAPI
@@ -19,19 +91,26 @@
USHORT *Segment,
USHORT *Offset)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;;
-
-}
-
-BOOLEAN
-NTAPI
-x86BiosCall (
- ULONG InterruptNumber,
- X86_BIOS_REGISTERS *Registers)
-{
- UNIMPLEMENTED;
- return FALSE;
+ /* Check if the system is initialized and the buffer is large enough */
+ if (!x86BiosIsInitialized || *Size > PAGE_SIZE)
+ {
+ /* Something was wrong, fail! */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Check if the buffer is already allocated */
+ if (InterlockedBitTestAndSet(&x86BiosBufferIsAllocated, 0))
+ {
+ /* Buffer was already allocated, fail */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* The buffer is sufficient, return hardcoded address and size */
+ *Size = PAGE_SIZE;
+ *Segment = 0x2000;
+ *Offset = 0;
+
+ return STATUS_SUCCESS;;
}
NTSTATUS
@@ -40,19 +119,49 @@
USHORT Segment,
USHORT Offset)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;;
+ /* Check if the system is initialized and if the address matches */
+ if (!x86BiosIsInitialized || Segment != 0x2000 || Offset != 0)
+ {
+ /* Something was wrong, fail */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check if the buffer was allocated */
+ if (!InterlockedBitTestAndReset(&x86BiosBufferIsAllocated, 0))
+ {
+ /* It was not, fail */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Buffer is freed, nothing more to do */
+ return STATUS_SUCCESS;;
}
NTSTATUS
+NTAPI
x86BiosReadMemory (
USHORT Segment,
USHORT Offset,
PVOID Buffer,
ULONG Size)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;;
+ ULONG_PTR Address;
+
+ /* Calculate the physical address */
+ Address = (Segment << 4) + Offset;
+
+ /* Check if it's valid */
+ if (!x86BiosIsInitialized || Address + Size > 0x100000)
+ {
+ /* Invalid */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Copy the memory to the buffer */
+ RtlCopyMemory(Buffer, x86BiosMemoryMapping + Address, Size);
+
+ /* Return success */
+ return STATUS_SUCCESS;
}
NTSTATUS
@@ -63,7 +172,146 @@
PVOID Buffer,
ULONG Size)
{
+ ULONG_PTR Address;
+
+ /* Calculate the physical address */
+ Address = (Segment << 4) + Offset;
+
+ /* Check if it's valid */
+ if (!x86BiosIsInitialized || Address + Size > 0x100000)
+ {
+ /* Invalid */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Copy the memory from the buffer */
+ RtlCopyMemory(x86BiosMemoryMapping + Address, Buffer, Size);
+
+ /* Return success */
+ return STATUS_SUCCESS;
+}
+
+typedef struct
+{
+ union
+ {
+ ULONG Eax;
+ USHORT Ax;
+ struct
+ {
+ UCHAR Al;
+ UCHAR Ah;
+ };
+ };
+ union
+ {
+ ULONG Ecx;
+ USHORT Cx;
+ struct
+ {
+ UCHAR Cl;
+ UCHAR Ch;
+ };
+ };
+ union
+ {
+ ULONG Edx;
+ USHORT Dx;
+ struct
+ {
+ UCHAR Dl;
+ UCHAR Dh;
+ };
+ };
+ union
+ {
+ ULONG Ebx;
+ USHORT Bx;
+ struct
+ {
+ UCHAR Bl;
+ UCHAR Bh;
+ };
+ };
+ ULONG Ebp;
+ ULONG Esi;
+ ULONG Edi;
+ USHORT SegDs;
+ USHORT SegEs;
+
+ /* Extended */
+ union
+ {
+ ULONG Eip;
+ USHORT Ip;
+ };
+
+ union
+ {
+ ULONG Esp;
+ USHORT Sp;
+ };
+
+} X86_REGISTERS, *PX86_REGISTERS;
+
+enum
+{
+ X86_VMFLAGS_RETURN_ON_IRET = 1,
+};
+
+typedef struct
+{
+ union
+ {
+ X86_BIOS_REGISTERS BiosRegisters;
+ X86_REGISTERS Registers;
+ };
+
+ struct
+ {
+ ULONG ReturnOnIret:1;
+ } Flags;
+
+ PVOID MemBuffer;
+} X86_VM_STATE, *PX86_VM_STATE;
+
+BOOLEAN
+NTAPI
+x86BiosCall (
+ ULONG InterruptNumber,
+ X86_BIOS_REGISTERS *Registers)
+{
+ X86_VM_STATE VmState;
+
+ /* Zero the VmState */
+ RtlZeroMemory(&VmState, sizeof(VmState));
+
+ /* Copy the registers */
+ VmState.BiosRegisters = *Registers;
+
+ /* Set the physical memory buffer */
+ VmState.MemBuffer = x86BiosMemoryMapping;
+
+ /* Initialize IP from the interrupt vector table */
+ VmState.Registers.Ip = ((PUSHORT)x86BiosMemoryMapping)[InterruptNumber];
+
+ /* Make the function return on IRET */
+ VmState.Flags.ReturnOnIret = 1;
+
+ /* Call the x86 emulator */
+// x86Emulator(&VmState);
+
+ /* Copy registers back to caller */
+ *Registers = VmState.BiosRegisters;
+
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+HalpBiosDisplayReset(VOID)
+{
UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;;
-}
-
+ return TRUE;
+}
+