Index: MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c =================================================================== --- MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c (revision 9332) +++ MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c (working copy) @@ -10,7 +10,7 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -**/ +**/ #include @@ -153,7 +153,134 @@ Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size); } +#ifdef VBOX +#define ACPI_RSD_PTR SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') +#define EBDA_BASE (0x9FC0 << 4) + +VOID * +FindAcpiRsdPtr ( + VOID + ) +{ + UINTN Address; + UINTN Index; + + // + // First Search 0x0e0000 - 0x0fffff for RSD Ptr + // + for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) { + if (*(UINT64 *)(Address) == ACPI_RSD_PTR) { + return (VOID *)Address; + } + } + + // + // Search EBDA + // + + Address = EBDA_BASE; + for (Index = 0; Index < 0x400 ; Index += 16) { + if (*(UINT64 *)(Address + Index) == ACPI_RSD_PTR) { + return (VOID *)Address; + } + } + return NULL; +} + +VOID* FindSignature(VOID* Start, UINT32 Signature, BOOLEAN NoChecksum) +{ + UINT8* Ptr = (UINT8*)Start; + UINT32 Count = 0x10000; // 16 pages + + while (Count-- > 0) + { + if ( *(UINT32*)Ptr == Signature + && ((EFI_ACPI_DESCRIPTION_HEADER *)Ptr)->Length <= Count + && (NoChecksum || + CalculateCheckSum8(Ptr, ((EFI_ACPI_DESCRIPTION_HEADER *)Ptr)->Length) == 0 + )) + { + return Ptr; + } + + Ptr++; + } + return NULL; +} + +VOID +FillSysTablesInfo(VOID** Tables, UINT32 TablesSize) +{ + UINT32 Table = 0; + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER* RsdPtr; + VOID* TablesPage; +#define FLAG_OPTIONAL 1<<0 +#define FLAG_NO_CHECKSUM 1<<1 + static struct { + UINT32 Signature; + UINT32 Flags; + CHAR8* Name; + } TableInfo[] = { + // MADT, optional + { SIGNATURE_32('A', 'P', 'I', 'C'), FLAG_OPTIONAL, "MADT"}, + // FACP (also called FADT) + { SIGNATURE_32('F', 'A', 'C', 'P'), 0, "FADT"}, + // FACS, according 5.2.9 of ACPI v2. spec FACS doesn't have checksum field + { SIGNATURE_32('F', 'A', 'C', 'S'), FLAG_NO_CHECKSUM, "FACS"}, + // DSDT + { SIGNATURE_32('D', 'S', 'D', 'T'), 0, "DSDT"}, + // SSDT + { SIGNATURE_32('S', 'S', 'D', 'T'), 0, "SSDT"}, + // HPET + { SIGNATURE_32('H', 'P', 'E', 'T'), FLAG_OPTIONAL, "HPET"} + }; + UINT32 Index; + + RsdPtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER*)FindAcpiRsdPtr(); + ASSERT(RsdPtr != NULL); + TablesPage = (VOID*)(UINTN)((RsdPtr->RsdtAddress) & ~0xfff); + + for (Index = 0; Index < sizeof TableInfo / sizeof TableInfo[0]; Index++) + { + VOID* Ptr = FindSignature(TablesPage, TableInfo[Index].Signature, + (BOOLEAN)((TableInfo[Index].Flags & FLAG_NO_CHECKSUM) != 0)); + if (TableInfo[Index].Signature == SIGNATURE_32('F', 'A', 'C', 'P')) + { + // we actually have 2 FADTs, see https://xtracker.innotek.de/index.php?bug=4082 + Ptr = FindSignature((UINT8*)Ptr+32, SIGNATURE_32('F', 'A', 'C', 'P'), FALSE); + } + if (!(TableInfo[Index].Flags & FLAG_OPTIONAL)) + ASSERT(Ptr != NULL); + DEBUG ((EFI_D_ERROR, "%a: %p\n", TableInfo[Index].Name, Ptr)); + Tables[Table++] = Ptr; + } + +#if 0 + // RSDT + ASSERT(Table < TablesSize); + Tables[Table] = FindSignature(TablesPage, SIGNATURE_32('R', 'S', 'D', 'T')); + DEBUG ((EFI_D_ERROR, "RSDT: %p\n", Tables[Table])); + ASSERT(Tables[Table] != NULL); + Table++; + + // XSDT + ASSERT(Table < TablesSize); + Tables[Table] = FindSignature(TablesPage, SIGNATURE_32('X', 'S', 'D', 'T')); + DEBUG ((EFI_D_ERROR, "XSDT: %p\n", Tables[Table])); + ASSERT(Tables[Table] != NULL); + Table++; +#endif + + DEBUG((DEBUG_INFO, "We found %d tables from %d\n", Table, TablesSize)); + Tables[Table] = NULL; +} +#endif + +#ifdef VBOX +#define USE_MEM_TABLES 1 +#endif + /** Entrypoint of Acpi Platform driver. @@ -174,14 +301,21 @@ { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; +#if USE_MEM_TABLES + VOID *VBoxTables[10]; +#else EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; +#endif INTN Instance; EFI_ACPI_COMMON_HEADER *CurrentTable; UINTN TableHandle; +#if !USE_MEM_TABLES UINT32 FvStatus; +#endif UINTN TableSize; UINTN Size; + Size = 0; Instance = 0; CurrentTable = NULL; TableHandle = 0; @@ -194,6 +327,18 @@ return EFI_ABORTED; } +#if USE_MEM_TABLES + /* VBOX already has tables prepared in memory - just reuse it */ + FillSysTablesInfo(VBoxTables, sizeof(VBoxTables)/sizeof(VBoxTables[0])); + while (Status == EFI_SUCCESS) { + CurrentTable = (EFI_ACPI_COMMON_HEADER*)VBoxTables[Instance]; + Status = (CurrentTable == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; + if (CurrentTable) + { + Size = CurrentTable->Length; + DEBUG ((EFI_D_ERROR, "adding %p %d\n", CurrentTable, Size)); + } +#else // // Locate the firmware volume protocol // @@ -205,7 +350,6 @@ // Read tables from the storage file. // while (Status == EFI_SUCCESS) { - Status = FwVol->ReadSection ( FwVol, (EFI_GUID*)FixedPcdGetPtr (PcdAcpiTableStorageFile), @@ -215,6 +359,7 @@ &Size, &FvStatus ); +#endif if (!EFI_ERROR(Status)) { // // Add the table @@ -222,6 +367,7 @@ TableHandle = 0; TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length; + DEBUG((DEBUG_INFO, "Size:%d, TableSize:%d\n", Size, TableSize)); ASSERT (Size >= TableSize); // @@ -252,4 +398,3 @@ return EFI_SUCCESS; } -