[HAL:X64] Fix/improve the BIOS interface
[reactos.git] / hal / halx86 / amd64 / x86bios.c
index a8b7d94..a361196 100644 (file)
 
 #include <fast486.h>
 
-/* This page serves as fallback for pages used by Mm */
-#define DEFAULT_PAGE 0x21
-
 /* GLOBALS *******************************************************************/
 
+/* This page serves as fallback for pages used by Mm */
+PFN_NUMBER x86BiosFallbackPfn;
+
 BOOLEAN x86BiosIsInitialized;
 LONG x86BiosBufferIsAllocated = 0;
 PUCHAR x86BiosMemoryMapping;
 
+/* This the physical address of the bios buffer */
+ULONG64 x86BiosBufferPhysical;
 
 VOID
 NTAPI
@@ -44,7 +46,7 @@ DbgDumpPage(PUCHAR MemBuffer, USHORT Segment)
 VOID
 NTAPI
 HalInitializeBios(
-    _In_ ULONG Unknown,
+    _In_ ULONG Phase,
     _In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
     PPFN_NUMBER PfnArray;
@@ -52,63 +54,97 @@ HalInitializeBios(
     PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
     PLIST_ENTRY ListEntry;
     PMDL Mdl;
+    ULONG64 PhysicalAddress;
 
-    /* Allocate an MDL for 1MB */
-    Mdl = IoAllocateMdl(NULL, 0x100000, FALSE, FALSE, NULL);
-    if (!Mdl)
+    if (Phase == 0)
     {
-        ASSERT(FALSE);
-    }
+        /* Allocate one page for a fallback mapping */
+        PhysicalAddress = HalpAllocPhysicalMemory(LoaderBlock,
+                                                  0x100000,
+                                                  1,
+                                                  FALSE);
+        if (PhysicalAddress == 0)
+        {
+            ASSERT(FALSE);
+        }
 
-    /* Get pointer to the pfn array */
-    PfnArray = MmGetMdlPfnArray(Mdl);
+        x86BiosFallbackPfn = PhysicalAddress / PAGE_SIZE;
+        ASSERT(x86BiosFallbackPfn != 0);
 
-    /* Fill the array with low memory PFNs */
-    for (Pfn = 0; Pfn < 0x100; Pfn++)
-    {
-        PfnArray[Pfn] = Pfn;
+        /* Allocate a page for the buffer allocation */
+        x86BiosBufferPhysical = HalpAllocPhysicalMemory(LoaderBlock,
+                                                        0x100000,
+                                                        1,
+                                                        FALSE);
+        if (x86BiosBufferPhysical == 0)
+        {
+            ASSERT(FALSE);
+        }
     }
-
-    /* Loop the memory descriptors */
-    for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
-         ListEntry != &LoaderBlock->MemoryDescriptorListHead;
-         ListEntry = ListEntry->Flink)
+    else
     {
-        /* 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)
+        /* Allocate an MDL for 1MB */
+        Mdl = IoAllocateMdl(NULL, 0x100000, FALSE, FALSE, NULL);
+        if (!Mdl)
         {
-            /* Check if the memory type is firmware */
-            if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
-                Descriptor->MemoryType != LoaderSpecialMemory)
+            ASSERT(FALSE);
+        }
+
+        /* Get pointer to the pfn array */
+        PfnArray = MmGetMdlPfnArray(Mdl);
+
+        /* Fill the array with the fallback page */
+        for (Pfn = 0; Pfn < 0x100; Pfn++)
+        {
+            PfnArray[Pfn] = x86BiosFallbackPfn;
+        }
+
+        /* 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 1 MB range */
+            if (Descriptor->BasePage < 0x100)
             {
-                /* It's something else, so don't use it! */
-                Last = min(Descriptor->BasePage + Descriptor->PageCount, 0x100);
-                for (Pfn = Descriptor->BasePage; Pfn < Last; Pfn++)
+                /* Check if the memory type is firmware */
+                if ((Descriptor->MemoryType == LoaderFirmwarePermanent) ||
+                    (Descriptor->MemoryType == LoaderSpecialMemory))
                 {
-                    /* Set each page to the default page */
-                    PfnArray[Pfn] = DEFAULT_PAGE;
+                    /* It's firmware, so map it! */
+                    Last = min(Descriptor->BasePage + Descriptor->PageCount, 0x100);
+                    for (Pfn = Descriptor->BasePage; Pfn < Last; Pfn++)
+                    {
+                        /* Set each physical page in the MDL */
+                        PfnArray[Pfn] = Pfn;
+                    }
                 }
             }
         }
-    }
 
-    Mdl->MdlFlags = MDL_PAGES_LOCKED;
+        /* Map this page proper, too */
+        Pfn = x86BiosBufferPhysical / PAGE_SIZE;
+        PfnArray[Pfn] = Pfn;
+
+        Mdl->MdlFlags = MDL_PAGES_LOCKED;
 
-    /* Map the MDL to system space */
-    x86BiosMemoryMapping = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority);
-    ASSERT(x86BiosMemoryMapping);
+        /* Map the MDL to system space */
+        x86BiosMemoryMapping = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority);
+        ASSERT(x86BiosMemoryMapping);
 
-    DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping, *(PVOID*)(x86BiosMemoryMapping + 8));
-    //DbgDumpPage(x86BiosMemoryMapping, 0xc351);
+        DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping, *(PVOID*)(x86BiosMemoryMapping + 8));
+        //DbgDumpPage(x86BiosMemoryMapping, 0xc351);
 
-    x86BiosIsInitialized = TRUE;
-    
-    HalpBiosDisplayReset();
+        x86BiosIsInitialized = TRUE;
+
+        HalpBiosDisplayReset();
+    }
 }
 
 NTSTATUS
@@ -134,7 +170,7 @@ x86BiosAllocateBuffer(
 
     /* The buffer is sufficient, return hardcoded address and size */
     *Size = PAGE_SIZE;
-    *Segment = 0x2000;
+    *Segment = x86BiosBufferPhysical / 16;
     *Offset = 0;
 
     return STATUS_SUCCESS;
@@ -291,7 +327,9 @@ ValidatePort(
         case 0x3B6: return (Size <= 2);
     }
 
-    return FALSE;
+    /* Allow but report unknown ports, we trust the BIOS for now */
+    DPRINT1("Unknown port 0x%x, size %d, write %d\n", Port, Size, IsWrite);
+    return TRUE;
 }
 
 static