b097ba371a
On UEFI systems, the SMBIOS entry point (a.k.a. anchor) structures are found similarly to the ACPI RSD PTR table(s): by scanning the ConfigurationTable array in the EFI system table for well-known GUIDs. Locate the SMBIOS 2.1 (32-bit) and 3.0 (64-bit) anchors in the BiosTablesTest UEFI application, and report the addresses in new fields appended to the BIOS_TABLES_TEST structure. Cc: "Philippe Mathieu-Daudé" <philmd@redhat.com> Cc: Igor Mammedov <imammedo@redhat.com> Launchpad: https://bugs.launchpad.net/qemu/+bug/1821884 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Igor Mammedov <imammedo@redhat.com>
146 lines
4.8 KiB
C
146 lines
4.8 KiB
C
/** @file
|
|
Populate the BIOS_TABLES_TEST structure.
|
|
|
|
Copyright (C) 2019, Red Hat, Inc.
|
|
|
|
This program and the accompanying materials are licensed and made available
|
|
under the terms and conditions of the BSD License that 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 <Guid/Acpi.h>
|
|
#include <Guid/BiosTablesTest.h>
|
|
#include <Guid/SmBios.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
|
|
/**
|
|
Wait for a keypress with a message that the application is about to exit.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
WaitForExitKeyPress (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Idx;
|
|
EFI_INPUT_KEY Key;
|
|
|
|
if (gST->ConIn == NULL) {
|
|
return;
|
|
}
|
|
AsciiPrint ("%a: press any key to exit\n", gEfiCallerBaseName);
|
|
Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Idx);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BiosTablesTestMain (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
VOID *Pages;
|
|
volatile BIOS_TABLES_TEST *BiosTablesTest;
|
|
CONST VOID *Rsdp10;
|
|
CONST VOID *Rsdp20;
|
|
CONST VOID *Smbios21;
|
|
CONST VOID *Smbios30;
|
|
CONST EFI_CONFIGURATION_TABLE *ConfigTable;
|
|
CONST EFI_CONFIGURATION_TABLE *ConfigTablesEnd;
|
|
volatile EFI_GUID *InverseSignature;
|
|
UINTN Idx;
|
|
|
|
Pages = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof *BiosTablesTest),
|
|
SIZE_1MB);
|
|
if (Pages == NULL) {
|
|
AsciiErrorPrint ("%a: AllocateAlignedPages() failed\n",
|
|
gEfiCallerBaseName);
|
|
//
|
|
// Assuming the application was launched by the boot manager as a boot
|
|
// loader, exiting with error will cause the boot manager to proceed with
|
|
// the remaining boot options. If there are no other boot options, the boot
|
|
// manager menu will be pulled up. Give the user a chance to read the error
|
|
// message.
|
|
//
|
|
WaitForExitKeyPress ();
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Locate all the gEfiAcpi10TableGuid, gEfiAcpi20TableGuid,
|
|
// gEfiSmbiosTableGuid, gEfiSmbios3TableGuid config tables in one go.
|
|
//
|
|
Rsdp10 = NULL;
|
|
Rsdp20 = NULL;
|
|
Smbios21 = NULL;
|
|
Smbios30 = NULL;
|
|
ConfigTable = gST->ConfigurationTable;
|
|
ConfigTablesEnd = gST->ConfigurationTable + gST->NumberOfTableEntries;
|
|
while ((Rsdp10 == NULL || Rsdp20 == NULL ||
|
|
Smbios21 == NULL || Smbios30 == NULL) &&
|
|
ConfigTable < ConfigTablesEnd) {
|
|
if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi10TableGuid)) {
|
|
Rsdp10 = ConfigTable->VendorTable;
|
|
} else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi20TableGuid)) {
|
|
Rsdp20 = ConfigTable->VendorTable;
|
|
} else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiSmbiosTableGuid)) {
|
|
Smbios21 = ConfigTable->VendorTable;
|
|
} else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiSmbios3TableGuid)) {
|
|
Smbios30 = ConfigTable->VendorTable;
|
|
}
|
|
++ConfigTable;
|
|
}
|
|
|
|
AsciiPrint ("%a: BiosTablesTest=%p Rsdp10=%p Rsdp20=%p\n",
|
|
gEfiCallerBaseName, Pages, Rsdp10, Rsdp20);
|
|
AsciiPrint ("%a: Smbios21=%p Smbios30=%p\n", gEfiCallerBaseName, Smbios21,
|
|
Smbios30);
|
|
|
|
//
|
|
// Store the config table addresses first, then the signature second.
|
|
//
|
|
BiosTablesTest = Pages;
|
|
BiosTablesTest->Rsdp10 = (UINTN)Rsdp10;
|
|
BiosTablesTest->Rsdp20 = (UINTN)Rsdp20;
|
|
BiosTablesTest->Smbios21 = (UINTN)Smbios21;
|
|
BiosTablesTest->Smbios30 = (UINTN)Smbios30;
|
|
|
|
MemoryFence();
|
|
|
|
InverseSignature = &BiosTablesTest->InverseSignatureGuid;
|
|
InverseSignature->Data1 = gBiosTablesTestGuid.Data1;
|
|
InverseSignature->Data1 ^= MAX_UINT32;
|
|
InverseSignature->Data2 = gBiosTablesTestGuid.Data2;
|
|
InverseSignature->Data2 ^= MAX_UINT16;
|
|
InverseSignature->Data3 = gBiosTablesTestGuid.Data3;
|
|
InverseSignature->Data3 ^= MAX_UINT16;
|
|
for (Idx = 0; Idx < sizeof InverseSignature->Data4; ++Idx) {
|
|
InverseSignature->Data4[Idx] = gBiosTablesTestGuid.Data4[Idx];
|
|
InverseSignature->Data4[Idx] ^= MAX_UINT8;
|
|
}
|
|
|
|
//
|
|
// The wait below has dual purpose. First, it blocks the application without
|
|
// wasting VCPU cycles while the hypervisor is scanning guest RAM. Second,
|
|
// assuming the application was launched by the boot manager as a boot
|
|
// loader, exiting the app with success causes the boot manager to pull up
|
|
// the boot manager menu at once (regardless of other boot options); the wait
|
|
// gives the user a chance to read the info printed above.
|
|
//
|
|
WaitForExitKeyPress ();
|
|
return EFI_SUCCESS;
|
|
}
|