| /** @file |
| Provides library functions for common SMBIOS operations. Only available to DXE |
| and UEFI module types. |
| |
| |
| Copyright (c) 2012, Apple Inc. All rights reserved. |
| Portitions Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> |
| 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 <PiDxe.h> |
| #include <Library/BaseLib.h> |
| #include <Library/BaseMemoryLib.h> |
| #include <Library/DebugLib.h> |
| #include <Library/MemoryAllocationLib.h> |
| #include <Library/UefiBootServicesTableLib.h> |
| #include <Library/UefiLib.h> |
| #include <Library/SmbiosLib.h> |
| |
| |
| EFI_SMBIOS_PROTOCOL *gSmbios = NULL; |
| |
| |
| /** |
| Create an initial SMBIOS Table from an array of SMBIOS_TEMPLATE_ENTRY |
| entries. SMBIOS_TEMPLATE_ENTRY.NULL indicates the end of the table. |
| |
| @param Template Array of SMBIOS_TEMPLATE_ENTRY entries. |
| |
| @retval EFI_SUCCESS New SMBIOS tables were created. |
| @retval EFI_OUT_OF_RESOURCES New SMBIOS tables were not created. |
| **/ |
| EFI_STATUS |
| EFIAPI |
| SmbiosLibInitializeFromTemplate ( |
| IN SMBIOS_TEMPLATE_ENTRY *Template |
| ) |
| { |
| EFI_STATUS Status; |
| UINTN Index; |
| |
| if (Template == NULL) { |
| return EFI_INVALID_PARAMETER; |
| } |
| |
| Status = EFI_SUCCESS; |
| |
| for (Index = 0; Template[Index].Entry != NULL; Index++) { |
| Status = SmbiosLibCreateEntry (Template[Index].Entry, Template[Index].StringArray); |
| } |
| |
| return Status; |
| } |
| |
| |
| |
| /** |
| Create SMBIOS record. |
| |
| Converts a fixed SMBIOS structure and an array of pointers to strings into |
| an SMBIOS record where the strings are cat'ed on the end of the fixed record |
| and terminated via a double NULL and add to SMBIOS table. |
| |
| SMBIOS_TABLE_TYPE32 gSmbiosType12 = { |
| { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 }, |
| 1 // StringCount |
| }; |
| CHAR8 *gSmbiosType12Strings[] = { |
| "Not Found", |
| NULL |
| }; |
| |
| ... |
| CreateSmbiosEntry ( |
| (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12, |
| gSmbiosType12Strings |
| ); |
| |
| @param SmbiosEntry Fixed SMBIOS structure |
| @param StringArray Array of strings to convert to an SMBIOS string pack. |
| NULL is OK. |
| |
| **/ |
| EFI_STATUS |
| EFIAPI |
| SmbiosLibCreateEntry ( |
| IN SMBIOS_STRUCTURE *SmbiosEntry, |
| IN CHAR8 **StringArray |
| ) |
| { |
| EFI_STATUS Status; |
| EFI_SMBIOS_HANDLE SmbiosHandle; |
| EFI_SMBIOS_TABLE_HEADER *Record; |
| UINTN Index; |
| UINTN StringSize; |
| UINTN Size; |
| CHAR8 *Str; |
| |
| // Calculate the size of the fixed record and optional string pack |
| Size = SmbiosEntry->Length; |
| if (StringArray == NULL) { |
| Size += 2; // Min string section is double null |
| } else if (StringArray[0] == NULL) { |
| Size += 2; // Min string section is double null |
| } else { |
| for (Index = 0; StringArray[Index] != NULL; Index++) { |
| StringSize = AsciiStrSize (StringArray[Index]); |
| Size += StringSize; |
| } |
| // Don't forget the terminating double null |
| Size += 1; |
| } |
| |
| // Copy over Template |
| Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size); |
| if (Record == NULL) { |
| return EFI_OUT_OF_RESOURCES; |
| } |
| CopyMem (Record, SmbiosEntry, SmbiosEntry->Length); |
| |
| if (StringArray != NULL) { |
| // Append string pack |
| Str = ((CHAR8 *)Record) + Record->Length; |
| for (Index = 0; StringArray[Index] != NULL; Index++) { |
| StringSize = AsciiStrSize (StringArray[Index]); |
| CopyMem (Str, StringArray[Index], StringSize); |
| Str += StringSize; |
| } |
| *Str = 0; |
| } |
| |
| SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; |
| Status = gSmbios->Add ( |
| gSmbios, |
| gImageHandle, |
| &SmbiosHandle, |
| Record |
| ); |
| |
| FreePool (Record); |
| return Status; |
| } |
| |
| |
| |
| /** |
| Update the string associated with an existing SMBIOS record. |
| |
| This function allows the update of specific SMBIOS strings. The number of valid strings for any |
| SMBIOS record is defined by how many strings were present when Add() was called. |
| |
| @param[in] SmbiosHandle SMBIOS Handle of structure that will have its string updated. |
| @param[in] StringNumber The non-zero string number of the string to update. |
| @param[in] String Update the StringNumber string with String. |
| |
| @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated. |
| @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid. |
| @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports. |
| @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record. |
| **/ |
| EFI_STATUS |
| EFIAPI |
| SmbiosLibUpdateString ( |
| IN EFI_SMBIOS_HANDLE SmbiosHandle, |
| IN SMBIOS_TABLE_STRING StringNumber, |
| IN CHAR8 *String |
| ) |
| { |
| UINTN StringIndex; |
| |
| if (String == NULL) { |
| return EFI_INVALID_PARAMETER; |
| } |
| |
| if (*String == '\0') { |
| // A string with no data is not legal in SMBIOS |
| return EFI_INVALID_PARAMETER; |
| } |
| |
| StringIndex = StringNumber; |
| return gSmbios->UpdateString (gSmbios, &SmbiosHandle, &StringIndex, String); |
| } |
| |
| |
| /** |
| Update the string associated with an existing SMBIOS record. |
| |
| This function allows the update of specific SMBIOS strings. The number of valid strings for any |
| SMBIOS record is defined by how many strings were present when Add() was called. |
| |
| @param[in] SmbiosHandle SMBIOS Handle of structure that will have its string updated. |
| @param[in] StringNumber The non-zero string number of the string to update. |
| @param[in] String Update the StringNumber string with String. |
| |
| @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated. |
| @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid. |
| @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports. |
| @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record. |
| **/ |
| EFI_STATUS |
| EFIAPI |
| SmbiosLibUpdateUnicodeString ( |
| IN EFI_SMBIOS_HANDLE SmbiosHandle, |
| IN SMBIOS_TABLE_STRING StringNumber, |
| IN CHAR16 *String |
| ) |
| { |
| EFI_STATUS Status; |
| UINTN StringIndex; |
| CHAR8 *Ascii; |
| |
| if (String == NULL) { |
| return EFI_INVALID_PARAMETER; |
| } |
| |
| if (*String == '\0') { |
| // A string with no data is not legal in SMBIOS |
| return EFI_INVALID_PARAMETER; |
| } |
| |
| Ascii = AllocateZeroPool (StrSize (String)); |
| if (Ascii == NULL) { |
| return EFI_OUT_OF_RESOURCES; |
| } |
| UnicodeStrToAsciiStr (String, Ascii); |
| |
| StringIndex = StringNumber; |
| Status = gSmbios->UpdateString (gSmbios, &SmbiosHandle, &StringIndex, Ascii); |
| |
| FreePool (Ascii); |
| return Status; |
| } |
| |
| |
| /** |
| Allow caller to read a specific SMBIOS string |
| |
| @param[in] Header SMBIOS record that contains the string. |
| @param[in[ StringNumber Instance of SMBIOS string 1 - N. |
| |
| @retval NULL Instance of Type SMBIOS string was not found. |
| @retval Other Pointer to matching SMBIOS string. |
| **/ |
| CHAR8 * |
| EFIAPI |
| SmbiosLibReadString ( |
| IN SMBIOS_STRUCTURE *Header, |
| IN EFI_SMBIOS_STRING StringNumber |
| ) |
| { |
| CHAR8 *Data; |
| UINTN Match; |
| |
| Data = (CHAR8 *)Header + Header->Length; |
| for (Match = 1;!(*Data == 0 && *(Data+1) == 0); ) { |
| if (StringNumber == Match) { |
| return Data; |
| } |
| Data++; |
| if (*(Data - 1) == '\0') { |
| Match++; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| |
| /** |
| Allow the caller to discover a specific SMBIOS entry, and patch it if necissary. |
| |
| @param[in] Type Type of the next SMBIOS record to return. |
| @param[in[ Instance Instance of SMBIOS record 0 - N-1. |
| @param[out] SmbiosHandle Returns SMBIOS handle for the matching record. |
| |
| @retval NULL Instance of Type SMBIOS record was not found. |
| @retval Other Pointer to matching SMBIOS record. |
| **/ |
| SMBIOS_STRUCTURE * |
| EFIAPI |
| SmbiosLibGetRecord ( |
| IN EFI_SMBIOS_TYPE Type, |
| IN UINTN Instance, |
| OUT EFI_SMBIOS_HANDLE *SmbiosHandle |
| ) |
| { |
| EFI_STATUS Status; |
| EFI_SMBIOS_TABLE_HEADER *Record; |
| UINTN Match; |
| |
| Match = 0; |
| *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; |
| do { |
| Status = gSmbios->GetNext (gSmbios, SmbiosHandle, &Type, &Record, NULL); |
| if (!EFI_ERROR (Status)) { |
| if (Match == Instance) { |
| return (SMBIOS_STRUCTURE *)Record; |
| } |
| Match++; |
| } |
| } while (!EFI_ERROR (Status)); |
| |
| return NULL; |
| } |
| |
| |
| /** |
| Remove an SMBIOS record. |
| |
| This function removes an SMBIOS record using the handle specified by SmbiosHandle. |
| |
| @param[in] SmbiosHandle The handle of the SMBIOS record to remove. |
| |
| @retval EFI_SUCCESS SMBIOS record was removed. |
| @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record. |
| **/ |
| EFI_STATUS |
| EFIAPI |
| SmbiosLibRemove ( |
| OUT EFI_SMBIOS_HANDLE SmbiosHandle |
| ) |
| { |
| return gSmbios->Remove (gSmbios, SmbiosHandle); |
| } |
| |
| |
| |
| /** |
| |
| @param ImageHandle ImageHandle of the loaded driver. |
| @param SystemTable Pointer to the EFI System Table. |
| |
| @retval EFI_SUCCESS Register successfully. |
| @retval EFI_OUT_OF_RESOURCES No enough memory to register this handler. |
| **/ |
| EFI_STATUS |
| EFIAPI |
| SmbiosLibConstructor ( |
| IN EFI_HANDLE ImageHandle, |
| IN EFI_SYSTEM_TABLE *SystemTable |
| ) |
| { |
| return gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&gSmbios); |
| } |
| |