diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables')
4 files changed, 960 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/LegacyBiosMpTable.h b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/LegacyBiosMpTable.h new file mode 100644 index 00000000..31dd9692 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/LegacyBiosMpTable.h @@ -0,0 +1,319 @@ +/* $Id: LegacyBiosMpTable.h $ */ +/** @file + * LegacyBiosMpTable.h + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +/*++ + +This code is based on: + +Copyright (c) 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + LegacyBiosMpTable.h + +Abstract: + Defines data structures per Multi Processor Specification Ver 1.4. + +--*/ + +#ifndef LEGACY_BIOS_MPTABLE_H_ +#define LEGACY_BIOS_MPTABLE_H_ + +#define EFI_LEGACY_MP_TABLE_REV_1_4 0x04 + +// +// Define MP table structures. All are packed. +// +#pragma pack(push, 1) + +#define EFI_LEGACY_MP_TABLE_FLOATING_POINTER_SIGNATURE SIGNATURE_32 ('_', 'M', 'P', '_') +typedef struct { + UINT32 Signature; + UINT32 PhysicalAddress; + UINT8 Length; + UINT8 SpecRev; + UINT8 Checksum; + UINT8 FeatureByte1; + struct { + UINT32 Reserved1 : 6; + UINT32 MutipleClk : 1; + UINT32 Imcr : 1; + UINT32 Reserved2 : 24; + } FeatureByte2_5; +} EFI_LEGACY_MP_TABLE_FLOATING_POINTER; + +#define EFI_LEGACY_MP_TABLE_HEADER_SIGNATURE SIGNATURE_32 ('P', 'C', 'M', 'P') +typedef struct { + UINT32 Signature; + UINT16 BaseTableLength; + UINT8 SpecRev; + UINT8 Checksum; + CHAR8 OemId[8]; + CHAR8 OemProductId[12]; + UINT32 OemTablePointer; + UINT16 OemTableSize; + UINT16 EntryCount; + UINT32 LocalApicAddress; + UINT16 ExtendedTableLength; + UINT8 ExtendedChecksum; + UINT8 Reserved; +} EFI_LEGACY_MP_TABLE_HEADER; + +typedef struct { + UINT8 EntryType; +} EFI_LEGACY_MP_TABLE_ENTRY_TYPE; + +// +// Entry Type 0: Processor. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_PROCESSOR 0x00 +typedef struct { + UINT8 EntryType; + UINT8 Id; + UINT8 Ver; + struct { + UINT8 Enabled : 1; + UINT8 Bsp : 1; + UINT8 Reserved : 6; + } Flags; + struct { + UINT32 Stepping : 4; + UINT32 Model : 4; + UINT32 Family : 4; + UINT32 Reserved : 20; + } Signature; + struct { + UINT32 Fpu : 1; + UINT32 Reserved1 : 6; + UINT32 Mce : 1; + UINT32 Cx8 : 1; + UINT32 Apic : 1; + UINT32 Reserved2 : 22; + } Features; + UINT32 Reserved1; + UINT32 Reserved2; +} EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR; + +// +// Entry Type 1: Bus. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_BUS 0x01 +typedef struct { + UINT8 EntryType; + UINT8 Id; + CHAR8 TypeString[6]; +} EFI_LEGACY_MP_TABLE_ENTRY_BUS; + +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_CBUS "CBUS " // Corollary CBus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_CBUSII "CBUSII" // Corollary CBUS II +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_EISA "EISA " // Extended ISA +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_FUTURE "FUTURE" // IEEE FutureBus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_INTERN "INTERN" // Internal bus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_ISA "ISA " // Industry Standard Architecture +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MBI "MBI " // Multibus I +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MBII "MBII " // Multibus II +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MCA "MCA " // Micro Channel Architecture +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MPI "MPI " // MPI +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MPSA "MPSA " // MPSA +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_NUBUS "NUBUS " // Apple Macintosh NuBus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_PCI "PCI " // Peripheral Component Interconnect +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_PCMCIA "PCMCIA" // PC Memory Card International Assoc. +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_TC "TC " // DEC TurboChannel +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_VL "VL " // VESA Local Bus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_VME "VME " // VMEbus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_XPRESS "XPRESS" // Express System Bus +// +// Entry Type 2: I/O APIC. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_IOAPIC 0x02 +typedef struct { + UINT8 EntryType; + UINT8 Id; + UINT8 Ver; + struct { + UINT8 Enabled : 1; + UINT8 Reserved : 7; + } Flags; + UINT32 Address; +} EFI_LEGACY_MP_TABLE_ENTRY_IOAPIC; + +// +// Entry Type 3: I/O Interrupt Assignment. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_IO_INT 0x03 +typedef struct { + UINT8 EntryType; + UINT8 IntType; + struct { + UINT16 Polarity : 2; + UINT16 Trigger : 2; + UINT16 Reserved : 12; + } Flags; + UINT8 SourceBusId; + union { + struct { + UINT8 IntNo : 2; + UINT8 Dev : 5; + UINT8 Reserved : 1; + } fields; + UINT8 byte; + } SourceBusIrq; + UINT8 DestApicId; + UINT8 DestApicIntIn; +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT; + +typedef enum { + EfiLegacyMpTableEntryIoIntTypeInt = 0, + EfiLegacyMpTableEntryIoIntTypeNmi = 1, + EfiLegacyMpTableEntryIoIntTypeSmi = 2, + EfiLegacyMpTableEntryIoIntTypeExtInt= 3, +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT_TYPE; + +typedef enum { + EfiLegacyMpTableEntryIoIntFlagsPolaritySpec = 0x0, + EfiLegacyMpTableEntryIoIntFlagsPolarityActiveHigh = 0x1, + EfiLegacyMpTableEntryIoIntFlagsPolarityReserved = 0x2, + EfiLegacyMpTableEntryIoIntFlagsPolarityActiveLow = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT_FLAGS_POLARITY; + +typedef enum { + EfiLegacyMpTableEntryIoIntFlagsTriggerSpec = 0x0, + EfiLegacyMpTableEntryIoIntFlagsTriggerEdge = 0x1, + EfiLegacyMpTableEntryIoIntFlagsTriggerReserved = 0x2, + EfiLegacyMpTableEntryIoIntFlagsTriggerLevel = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT_FLAGS_TRIGGER; + +// +// Entry Type 4: Local Interrupt Assignment. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_LOCAL_INT 0x04 +typedef struct { + UINT8 EntryType; + UINT8 IntType; + struct { + UINT16 Polarity : 2; + UINT16 Trigger : 2; + UINT16 Reserved : 12; + } Flags; + UINT8 SourceBusId; + UINT8 SourceBusIrq; + UINT8 DestApicId; + UINT8 DestApicIntIn; +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT; + +typedef enum { + EfiLegacyMpTableEntryLocalIntTypeInt = 0, + EfiLegacyMpTableEntryLocalIntTypeNmi = 1, + EfiLegacyMpTableEntryLocalIntTypeSmi = 2, + EfiLegacyMpTableEntryLocalIntTypeExtInt = 3, +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT_TYPE; + +typedef enum { + EfiLegacyMpTableEntryLocalIntFlagsPolaritySpec = 0x0, + EfiLegacyMpTableEntryLocalIntFlagsPolarityActiveHigh= 0x1, + EfiLegacyMpTableEntryLocalIntFlagsPolarityReserved = 0x2, + EfiLegacyMpTableEntryLocalIntFlagsPolarityActiveLow = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT_FLAGS_POLARITY; + +typedef enum { + EfiLegacyMpTableEntryLocalIntFlagsTriggerSpec = 0x0, + EfiLegacyMpTableEntryLocalIntFlagsTriggerEdge = 0x1, + EfiLegacyMpTableEntryLocalIntFlagsTriggerReserved = 0x2, + EfiLegacyMpTableEntryLocalIntFlagsTriggerLevel = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT_FLAGS_TRIGGER; + +// +// Entry Type 128: System Address Space Mapping. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_EXT_TYPE_SYS_ADDR_SPACE_MAPPING 0x80 +typedef struct { + UINT8 EntryType; + UINT8 Length; + UINT8 BusId; + UINT8 AddressType; + UINT64 AddressBase; + UINT64 AddressLength; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_SYS_ADDR_SPACE_MAPPING; + +typedef enum { + EfiLegacyMpTableEntryExtSysAddrSpaceMappingIo = 0, + EfiLegacyMpTableEntryExtSysAddrSpaceMappingMemory = 1, + EfiLegacyMpTableEntryExtSysAddrSpaceMappingPrefetch = 2, +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_SYS_ADDR_SPACE_MAPPING_TYPE; + +// +// Entry Type 129: Bus Hierarchy. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_EXT_TYPE_BUS_HIERARCHY 0x81 +typedef struct { + UINT8 EntryType; + UINT8 Length; + UINT8 BusId; + struct { + UINT8 SubtractiveDecode : 1; + UINT8 Reserved : 7; + } BusInfo; + UINT8 ParentBus; + UINT8 Reserved1; + UINT8 Reserved2; + UINT8 Reserved3; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_BUS_HIERARCHY; + +// +// Entry Type 130: Compatibility Bus Address Space Modifier. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_EXT_TYPE_COMPAT_BUS_ADDR_SPACE_MODIFIER 0x82 +typedef struct { + UINT8 EntryType; + UINT8 Length; + UINT8 BusId; + struct { + UINT8 RangeMode : 1; + UINT8 Reserved : 7; + } AddrMode; + UINT32 PredefinedRangeList; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_COMPAT_BUS_ADDR_SPACE_MODIFIER; + +#pragma pack(pop) + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/TableConversion.c b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/TableConversion.c new file mode 100644 index 00000000..0cde7ef8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/TableConversion.c @@ -0,0 +1,380 @@ +/* $Id: TableConversion.c $ */ +/** @file + * TableConversion.c + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +/*++ + + This code is baed on: + + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + 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 <IndustryStandard/Pci.h> +#include <IndustryStandard/Acpi.h> +#include <IndustryStandard/SmBios.h> +#include "LegacyBiosMpTable.h" + +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseLib.h> + +#include <Guid/Acpi.h> +#include <Guid/SmBios.h> +#include <Guid/Mps.h> +#include <Guid/HobList.h> +#include <Guid/GlobalVariable.h> + +#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 ) +#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF + +EFI_STATUS +ConvertAcpiTable ( + IN UINTN TableLen, + IN OUT VOID **Table + ) +/*++ + + Routine Description: + Convert RSDP of ACPI Table if its location is lower than Address:0x100000 + Assumption here: + As in legacy Bios, ACPI table is required to place in E/F Seg, + So here we just check if the range is E/F seg, + and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS + + Arguments: + TableLen - Acpi RSDP length + Table - pointer to the table + + Returns: + EFI_SUCCESS - Convert Table successfully + Other - Failed + + --*/ +{ + VOID *AcpiTableOri; + VOID *AcpiTableNew; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS BufferPtr; + + + AcpiTableOri = (VOID *)(UINTN)((*Table)); + + BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES(TableLen), + &BufferPtr + ); + ASSERT_EFI_ERROR (Status); + AcpiTableNew = (VOID *)(UINTN)BufferPtr; + CopyMem (AcpiTableNew, AcpiTableOri, TableLen); + + // + // Change configuration table Pointer + // + *Table = AcpiTableNew; + + return EFI_SUCCESS; +} + +EFI_STATUS +ConvertSmbiosTable ( + IN OUT VOID **Table + ) +/*++ + + Routine Description: + + Convert Smbios Table if the Location of the SMBios Table is lower than Address 0x100000 + Assumption here: + As in legacy Bios, Smbios table is required to place in E/F Seg, + So here we just check if the range is F seg, + and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData + Arguments: + Table - pointer to the table + + Returns: + EFI_SUCCESS - Convert Table successfully + Other - Failed + + --*/ +{ + SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew; + SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri; + EFI_STATUS Status; + UINT32 SmbiosEntryLen; + UINT32 BufferLen; + EFI_PHYSICAL_ADDRESS BufferPtr; + + SmbiosTableNew = NULL; + SmbiosTableOri = NULL; + + // + // Get Smibos configuration Table + // + SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)((*Table)); + + + ASSERT(CalculateSum8((UINT8*)SmbiosTableOri, sizeof(SMBIOS_TABLE_ENTRY_POINT)) == 0); + // + // Relocate the Smibos memory + // + BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; + if (SmbiosTableOri->SmbiosBcdRevision != 0x21) { + SmbiosEntryLen = SmbiosTableOri->EntryPointLength; + } else { + // + // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1 + // + SmbiosEntryLen = 0x1F; + } + BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES(BufferLen), + &BufferPtr + ); + ASSERT_EFI_ERROR (Status); + SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr; + CopyMem ( + SmbiosTableNew, + SmbiosTableOri, + SmbiosEntryLen + ); + // + // Get Smbios Structure table address, and make sure the start address is 32-bit align + // + BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen); + CopyMem ( + (VOID *)(UINTN)BufferPtr, + (VOID *)(UINTN)(SmbiosTableOri->TableAddress), + SmbiosTableOri->TableLength + ); + SmbiosTableNew->TableAddress = (UINT32)BufferPtr; + SmbiosTableNew->IntermediateChecksum = 0; + SmbiosTableNew->IntermediateChecksum = + CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10); + // + // Change the SMBIOS pointer + // + *Table = SmbiosTableNew; + + return EFI_SUCCESS; +} + +EFI_STATUS +ConvertMpsTable ( + IN OUT VOID **Table + ) +/*++ + + Routine Description: + + Convert MP Table if the Location of the SMBios Table is lower than Address 0x100000 + Assumption here: + As in legacy Bios, MP table is required to place in E/F Seg, + So here we just check if the range is E/F seg, + and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData + Arguments: + Table - pointer to the table + + Returns: + EFI_SUCCESS - Convert Table successfully + Other - Failed + + --*/ +{ + UINT32 Data32; + UINT32 FPLength; + EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri; + EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew; + EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri; + EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew; + VOID *OemTableOri; + VOID *OemTableNew; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS BufferPtr; + + // + // Get MP configuration Table + // + MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*Table); + // + // Get Floating pointer structure length + // + FPLength = MpsFloatingPointerOri->Length * 16; + ASSERT(CalculateSum8((UINT8*)MpsFloatingPointerOri, FPLength) == 0); + Data32 = FPLength + SYS_TABLE_PAD (FPLength); + MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress); + ASSERT(MpsTableOri != NULL); + ASSERT(CalculateSum8((UINT8*)MpsTableOri, MpsTableOri->BaseTableLength) == 0); + + Data32 += MpsTableOri->BaseTableLength; + Data32 += MpsTableOri->ExtendedTableLength; + if (MpsTableOri->OemTablePointer != 0x00) { + Data32 += SYS_TABLE_PAD (Data32); + Data32 += MpsTableOri->OemTableSize; + } + + // + // Relocate memory + // + BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES(Data32), + &BufferPtr + ); + ASSERT_EFI_ERROR (Status); + MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr; + CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength); + // + // If Mp Table exists + // + if (MpsTableOri != NULL) { + // + // Get Mps table length, including Ext table + // + BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength); + MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr; + CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength); + + if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){ + BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength; + BufferPtr += SYS_TABLE_PAD (BufferPtr); + OemTableNew = (VOID *)(UINTN)BufferPtr; + OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer; + CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize); + MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew; + } + MpsTableNew->Checksum = 0; + MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength); + MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew; + MpsFloatingPointerNew->Checksum = 0; + MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength); + } + // + // Change the pointer + // + *Table = MpsFloatingPointerNew; + + return EFI_SUCCESS; +} + +EFI_STATUS +ConvertSystemTable ( + IN EFI_GUID *TableGuid, + IN OUT VOID **Table + ) +/*++ + + Routine Description: + Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000 + Assumption here: + As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg, + So here we just check if the range is E/F seg, + and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS + + Arguments: + TableGuid - Guid of the table + Table - pointer to the table + + Returns: + EFI_SUCCESS - Convert Table successfully + Other - Failed + + --*/ +{ + EFI_STATUS Status = EFI_SUCCESS; + VOID *AcpiHeader; + UINTN AcpiTableLen; + + // + // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version. + // + + if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){ + AcpiHeader = (VOID*)(UINTN)(*Table); + + if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){ + // + // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size + // + AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER); + } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){ + // + // If Acpi 2.0 or later, use RSDP Length fied. + // + AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length; + } else { + // + // Invalid Acpi Version, return + // + return EFI_UNSUPPORTED; + } + Status = ConvertAcpiTable (AcpiTableLen, Table); + return Status; + } + + // + // If matches smbios guid, convert Smbios table. + // + if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){ + Status = ConvertSmbiosTable (Table); + return Status; + } + + // + // If the table is MP table? + // + if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){ + Status = ConvertMpsTable (Table); + return Status; + } + + return EFI_UNSUPPORTED; +} diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/VBoxSysTables.c b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/VBoxSysTables.c new file mode 100644 index 00000000..06d0b6a9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/VBoxSysTables.c @@ -0,0 +1,178 @@ +/* $Id: VBoxSysTables.c $ */ +/** @file + * VBoxSysTables.c - VirtualBox system tables + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include <Protocol/DevicePathToText.h> + +#include <IndustryStandard/Acpi10.h> +#include <IndustryStandard/Acpi20.h> +#include <IndustryStandard/SmBios.h> + +#include <Guid/SmBios.h> +#include <Guid/Acpi.h> +#include <Guid/Mps.h> + +#include "VBoxPkg.h" +#include "DevEFI.h" +#include "iprt/asm.h" + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ + + +EFI_STATUS EFIAPI +ConvertSystemTable ( + IN EFI_GUID *TableGuid, + IN OUT VOID **Table + ); + +#define MPS_PTR SIGNATURE_32('_','M','P','_') +#define SMBIOS_PTR SIGNATURE_32('_','S','M','_') + +#define EBDA_BASE (0x9FC0 << 4) + +VOID * +FindSMBIOSPtr ( + VOID + ) +{ + UINTN Address; + + // + // First Search 0x0e0000 - 0x0fffff for SMBIOS Ptr + // + for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) { + if (*(UINT32 *)(Address) == SMBIOS_PTR) { + return (VOID *)Address; + } + } + return NULL; +} + +VOID * +FindMPSPtr ( + VOID + ) +{ + UINTN Address; + UINTN Index; + + // + // First Search 0x0e0000 - 0x0fffff for MPS Ptr + // + for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) { + if (*(UINT32 *)(Address) == MPS_PTR) { + return (VOID *)Address; + } + } + + // + // Search EBDA + // + + Address = EBDA_BASE; + for (Index = 0; Index < 0x400 ; Index += 16) { + if (*(UINT32 *)(Address + Index) == MPS_PTR) { + return (VOID *)(Address + Index); + } + } + return NULL; +} + +EFI_STATUS EFIAPI +ConvertAndInstallTable(EFI_GUID* Guid, VOID* Ptr) +{ + EFI_STATUS rc = EFI_SUCCESS; + + rc = ConvertSystemTable(Guid, &Ptr); + //ASSERT_EFI_ERROR (rc); + + rc = gBS->InstallConfigurationTable(Guid, Ptr); + ASSERT_EFI_ERROR (rc); + + return rc; +} + + +/** + * VBoxSysTablesDxe entry point. + * + * @returns EFI status code. + * + * @param ImageHandle The image handle. + * @param SystemTable The system table pointer. + */ +EFI_STATUS EFIAPI +DxeInitializeVBoxSysTables(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS rc; + VOID* Ptr; + + DEBUG((DEBUG_INFO, "DxeInitializeVBoxSysTables\n")); + + Ptr = FindSMBIOSPtr(); + DEBUG((DEBUG_INFO, "SMBIOS=%p\n", Ptr)); + ASSERT(Ptr != NULL); + if (Ptr) + { + rc = ConvertAndInstallTable(&gEfiSmbiosTableGuid, Ptr); + ASSERT_EFI_ERROR (rc); + } + + Ptr = FindMPSPtr(); + DEBUG((DEBUG_INFO, "MPS=%p\n", Ptr)); + // MPS can be null in non IO-APIC configs + if (Ptr) + rc = ConvertAndInstallTable(&gEfiMpsTableGuid, Ptr); + + return EFI_SUCCESS; +} + +EFI_STATUS EFIAPI +DxeUninitializeVBoxSysTables(IN EFI_HANDLE ImageHandle) +{ + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/VBoxSysTables.inf b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/VBoxSysTables.inf new file mode 100644 index 00000000..51299160 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxSysTables/VBoxSysTables.inf @@ -0,0 +1,83 @@ +# $Id: VBoxSysTables.inf $ +## @file +# VBoxSysTables - VBox system tables. +# + +# +# Copyright (C) 2010-2022 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VBoxSysTables + FILE_GUID = 3749CF40-9086-4488-BB8E-44C9400D260F + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 +# SUPPORTED_ARCHITECTURES = IA32|X64|IPF|EBC + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + ENTRY_POINT = DxeInitializeVBoxSysTables + UNLOAD_IMAGE = DxeUninitializeVBoxSysTables + +[Sources.common] + VBoxSysTables.c + TableConversion.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + VBoxPkg/VBoxPkg.dec + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + PcdLib + DevicePathLib + +[Guids] + gEfiSmbiosTableGuid + gEfiAcpiTableGuid + gEfiAcpi20TableGuid + gEfiMpsTableGuid + +[Protocols] + gEfiDevicePathToTextProtocolGuid + +[BuildOptions.common] + + GCC:*_*_*_CC_FLAGS = + INTEL:*_*_*_CC_FLAGS = + MSFT:*_*_*_CC_FLAGS = |