[HAL:X64] Fix/improve the BIOS interface

* Call HalInitializeBios both in phase 0 and 1
* In phase 0 allocate some physical memory, instead of using arbitrary hardcoded pages, that then end up as page tables and get filled with VESA tables
This commit is contained in:
Timo Kreuzer 2020-02-09 22:19:54 +01:00
parent 743c378ed1
commit c5a700fd06
3 changed files with 98 additions and 56 deletions

View file

@ -14,15 +14,17 @@
#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);
}
/* 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)
/* Allocate one page for a fallback mapping */
PhysicalAddress = HalpAllocPhysicalMemory(LoaderBlock,
0x100000,
1,
FALSE);
if (PhysicalAddress == 0)
{
/* Check if the memory type is firmware */
if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
Descriptor->MemoryType != LoaderSpecialMemory)
ASSERT(FALSE);
}
x86BiosFallbackPfn = PhysicalAddress / PAGE_SIZE;
ASSERT(x86BiosFallbackPfn != 0);
/* Allocate a page for the buffer allocation */
x86BiosBufferPhysical = HalpAllocPhysicalMemory(LoaderBlock,
0x100000,
1,
FALSE);
if (x86BiosBufferPhysical == 0)
{
ASSERT(FALSE);
}
}
else
{
/* 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 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;
}
}
}
}
/* 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);
DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping, *(PVOID*)(x86BiosMemoryMapping + 8));
//DbgDumpPage(x86BiosMemoryMapping, 0xc351);
x86BiosIsInitialized = TRUE;
HalpBiosDisplayReset();
}
Mdl->MdlFlags = MDL_PAGES_LOCKED;
/* 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);
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

View file

@ -136,6 +136,10 @@ HalInitSystem(IN ULONG BootPhase,
/* Do some HAL-specific initialization */
HalpInitPhase0(LoaderBlock);
#ifdef _M_AMD64
HalInitializeBios(0, LoaderBlock);
#endif
}
else if (BootPhase == 1)
{
@ -146,7 +150,7 @@ HalInitSystem(IN ULONG BootPhase,
HalpInitPhase1();
#ifdef _M_AMD64
HalInitializeBios(0, LoaderBlock);
HalInitializeBios(1, LoaderBlock);
#endif
}

View file

@ -534,7 +534,7 @@ extern ULONG PIT_FREQUENCY;
VOID
NTAPI
HalInitializeBios(
_In_ ULONG Unknown,
_In_ ULONG Phase,
_In_ PLOADER_PARAMETER_BLOCK LoaderBlock
);