/** @file This driver installs SMBIOS information for OVMF Copyright (c) 2020, Rebecca Cran Copyright (c) 2011, Bei Guan Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
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; }