mirror of https://github.com/acidanthera/audk.git
243 lines
6.4 KiB
C
243 lines
6.4 KiB
C
/** @file
|
|
This driver installs SMBIOS information for OVMF
|
|
|
|
Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
|
|
Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
|
|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "SmbiosPlatformDxe.h"
|
|
|
|
#define TYPE0_STRINGS \
|
|
"EFI Development Kit II / OVMF\0" /* Vendor */ \
|
|
"0.0.0\0" /* BiosVersion */ \
|
|
"02/06/2015\0" /* BiosReleaseDate */
|
|
//
|
|
// Type definition and contents of the default Type 0 SMBIOS table.
|
|
//
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
SMBIOS_TABLE_TYPE0 Base;
|
|
UINT8 Strings[sizeof (TYPE0_STRINGS)];
|
|
} OVMF_TYPE0;
|
|
#pragma pack()
|
|
|
|
STATIC CONST OVMF_TYPE0 mOvmfDefaultType0 = {
|
|
{
|
|
// SMBIOS_STRUCTURE Hdr
|
|
{
|
|
EFI_SMBIOS_TYPE_BIOS_INFORMATION, // UINT8 Type
|
|
sizeof (SMBIOS_TABLE_TYPE0), // UINT8 Length
|
|
},
|
|
1, // SMBIOS_TABLE_STRING Vendor
|
|
2, // SMBIOS_TABLE_STRING BiosVersion
|
|
0xE800, // UINT16 BiosSegment
|
|
3, // SMBIOS_TABLE_STRING BiosReleaseDate
|
|
0, // UINT8 BiosSize
|
|
{ // MISC_BIOS_CHARACTERISTICS BiosCharacteristics
|
|
0, // Reserved :2
|
|
0, // Unknown :1
|
|
1, // BiosCharacteristicsNotSupported :1
|
|
// Remaining BiosCharacteristics bits left unset :60
|
|
},
|
|
{ // BIOSCharacteristicsExtensionBytes[2]
|
|
0, // BiosReserved
|
|
0x1C // SystemReserved = VirtualMachineSupported |
|
|
// UefiSpecificationSupported |
|
|
// TargetContentDistributionEnabled
|
|
},
|
|
0, // UINT8 SystemBiosMajorRelease
|
|
0, // UINT8 SystemBiosMinorRelease
|
|
0xFF, // UINT8 EmbeddedControllerFirmwareMajorRelease
|
|
0xFF // UINT8 EmbeddedControllerFirmwareMinorRelease
|
|
},
|
|
// Text strings (unformatted area)
|
|
TYPE0_STRINGS
|
|
};
|
|
|
|
/**
|
|
Validates the SMBIOS entry point structure
|
|
|
|
@param EntryPointStructure SMBIOS entry point structure
|
|
|
|
@retval TRUE The entry point structure is valid
|
|
@retval FALSE The entry point structure is not valid
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsEntryPointStructureValid (
|
|
IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT8 Length;
|
|
UINT8 Checksum;
|
|
UINT8 *BytePtr;
|
|
|
|
BytePtr = (UINT8 *)EntryPointStructure;
|
|
Length = EntryPointStructure->EntryPointLength;
|
|
Checksum = 0;
|
|
|
|
for (Index = 0; Index < Length; Index++) {
|
|
Checksum = Checksum + (UINT8)BytePtr[Index];
|
|
}
|
|
|
|
if (Checksum != 0) {
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get SMBIOS record length.
|
|
|
|
@param SmbiosTable SMBIOS pointer.
|
|
|
|
**/
|
|
UINTN
|
|
SmbiosTableLength (
|
|
IN SMBIOS_STRUCTURE_POINTER SmbiosTable
|
|
)
|
|
{
|
|
CHAR8 *AChar;
|
|
UINTN Length;
|
|
|
|
AChar = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length);
|
|
|
|
//
|
|
// Each structure shall be terminated by a double-null (SMBIOS spec.7.1)
|
|
//
|
|
while ((*AChar != 0) || (*(AChar + 1) != 0)) {
|
|
AChar++;
|
|
}
|
|
|
|
Length = ((UINTN)AChar - (UINTN)SmbiosTable.Raw + 2);
|
|
|
|
return Length;
|
|
}
|
|
|
|
/**
|
|
Install all structures from the given SMBIOS structures block
|
|
|
|
@param Smbios SMBIOS protocol
|
|
@param TableAddress SMBIOS tables starting address
|
|
|
|
**/
|
|
EFI_STATUS
|
|
InstallAllStructures (
|
|
IN EFI_SMBIOS_PROTOCOL *Smbios,
|
|
IN UINT8 *TableAddress
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SMBIOS_STRUCTURE_POINTER SmbiosTable;
|
|
EFI_SMBIOS_HANDLE SmbiosHandle;
|
|
BOOLEAN NeedSmbiosType0;
|
|
|
|
SmbiosTable.Raw = TableAddress;
|
|
if (SmbiosTable.Raw == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
NeedSmbiosType0 = TRUE;
|
|
|
|
while (SmbiosTable.Hdr->Type != 127) {
|
|
//
|
|
// Log the SMBIOS data for this structure
|
|
//
|
|
SmbiosHandle = SmbiosTable.Hdr->Handle;
|
|
Status = Smbios->Add (
|
|
Smbios,
|
|
NULL,
|
|
&SmbiosHandle,
|
|
(EFI_SMBIOS_TABLE_HEADER *)SmbiosTable.Raw
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (SmbiosTable.Hdr->Type == 0) {
|
|
NeedSmbiosType0 = FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the next structure address
|
|
//
|
|
SmbiosTable.Raw = (UINT8 *)(SmbiosTable.Raw + SmbiosTableLength (SmbiosTable));
|
|
}
|
|
|
|
if (NeedSmbiosType0) {
|
|
//
|
|
// Add OVMF default Type 0 (BIOS Information) table
|
|
//
|
|
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
|
|
Status = Smbios->Add (
|
|
Smbios,
|
|
NULL,
|
|
&SmbiosHandle,
|
|
(EFI_SMBIOS_TABLE_HEADER *)&mOvmfDefaultType0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Installs SMBIOS information for OVMF
|
|
|
|
@param ImageHandle Module's image handle
|
|
@param SystemTable Pointer of EFI_SYSTEM_TABLE
|
|
|
|
@retval EFI_SUCCESS Smbios data successfully installed
|
|
@retval Other Smbios data was not installed
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SmbiosTablePublishEntry (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMBIOS_PROTOCOL *Smbios;
|
|
SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure;
|
|
UINT8 *SmbiosTables = NULL;
|
|
|
|
//
|
|
// Find the SMBIOS protocol
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSmbiosProtocolGuid,
|
|
NULL,
|
|
(VOID **)&Smbios
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Add bhyve SMBIOS data
|
|
//
|
|
EntryPointStructure = GetBhyveSmbiosTables ();
|
|
if (EntryPointStructure != NULL) {
|
|
SmbiosTables = (UINT8 *)(UINTN)EntryPointStructure->TableAddress;
|
|
}
|
|
|
|
if (SmbiosTables != NULL) {
|
|
Status = InstallAllStructures (Smbios, SmbiosTables);
|
|
|
|
//
|
|
// Free SmbiosTables if allocated by Qemu (i.e., NOT by Xen):
|
|
//
|
|
if (EntryPointStructure == NULL) {
|
|
FreePool (SmbiosTables);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|