Home | History | Annotate | Download | only in SmbiosLib
      1 /** @file
      2   Provides library functions for common SMBIOS operations. Only available to DXE
      3   and UEFI module types.
      4 
      5 
      6 Copyright (c) 2012, Apple Inc. All rights reserved.
      7 Portitions Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
      8 This program and the accompanying materials are licensed and made available under
      9 the terms and conditions of the BSD License that accompanies this distribution.
     10 The full text of the license may be found at
     11 http://opensource.org/licenses/bsd-license.php.
     12 
     13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include <PiDxe.h>
     19 #include <Library/BaseLib.h>
     20 #include <Library/BaseMemoryLib.h>
     21 #include <Library/DebugLib.h>
     22 #include <Library/MemoryAllocationLib.h>
     23 #include <Library/UefiBootServicesTableLib.h>
     24 #include <Library/UefiLib.h>
     25 #include <Library/SmbiosLib.h>
     26 
     27 
     28 EFI_SMBIOS_PROTOCOL *gSmbios = NULL;
     29 
     30 
     31 /**
     32   Create an initial SMBIOS Table from an array of SMBIOS_TEMPLATE_ENTRY
     33   entries. SMBIOS_TEMPLATE_ENTRY.NULL indicates the end of the table.
     34 
     35   @param  Template   Array of SMBIOS_TEMPLATE_ENTRY entries.
     36 
     37   @retval EFI_SUCCESS          New SMBIOS tables were created.
     38   @retval EFI_OUT_OF_RESOURCES New SMBIOS tables were not created.
     39 **/
     40 EFI_STATUS
     41 EFIAPI
     42 SmbiosLibInitializeFromTemplate (
     43   IN  SMBIOS_TEMPLATE_ENTRY   *Template
     44   )
     45 {
     46   EFI_STATUS    Status;
     47   UINTN         Index;
     48 
     49   if (Template == NULL) {
     50     return EFI_INVALID_PARAMETER;
     51   }
     52 
     53   Status = EFI_SUCCESS;
     54 
     55   for (Index = 0; Template[Index].Entry != NULL; Index++) {
     56     Status = SmbiosLibCreateEntry (Template[Index].Entry, Template[Index].StringArray);
     57   }
     58 
     59   return Status;
     60 }
     61 
     62 
     63 
     64 /**
     65   Create SMBIOS record.
     66 
     67   Converts a fixed SMBIOS structure and an array of pointers to strings into
     68   an SMBIOS record where the strings are cat'ed on the end of the fixed record
     69   and terminated via a double NULL and add to SMBIOS table.
     70 
     71   SMBIOS_TABLE_TYPE32 gSmbiosType12 = {
     72     { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 },
     73     1 // StringCount
     74   };
     75   CHAR8 *gSmbiosType12Strings[] = {
     76     "Not Found",
     77     NULL
     78   };
     79 
     80   ...
     81   CreateSmbiosEntry (
     82     (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12,
     83     gSmbiosType12Strings
     84     );
     85 
     86   @param  SmbiosEntry   Fixed SMBIOS structure
     87   @param  StringArray   Array of strings to convert to an SMBIOS string pack.
     88                         NULL is OK.
     89 
     90 **/
     91 EFI_STATUS
     92 EFIAPI
     93 SmbiosLibCreateEntry (
     94   IN  SMBIOS_STRUCTURE *SmbiosEntry,
     95   IN  CHAR8            **StringArray
     96   )
     97 {
     98   EFI_STATUS                Status;
     99   EFI_SMBIOS_HANDLE         SmbiosHandle;
    100   EFI_SMBIOS_TABLE_HEADER   *Record;
    101   UINTN                     Index;
    102   UINTN                     StringSize;
    103   UINTN                     Size;
    104   CHAR8                     *Str;
    105 
    106   // Calculate the size of the fixed record and optional string pack
    107   Size = SmbiosEntry->Length;
    108   if (StringArray == NULL) {
    109     Size += 2; // Min string section is double null
    110   } else if (StringArray[0] == NULL) {
    111     Size += 2; // Min string section is double null
    112   } else {
    113     for (Index = 0; StringArray[Index] != NULL; Index++) {
    114       StringSize = AsciiStrSize (StringArray[Index]);
    115       Size += StringSize;
    116     }
    117     // Don't forget the terminating double null
    118     Size += 1;
    119   }
    120 
    121   // Copy over Template
    122   Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size);
    123   if (Record == NULL) {
    124     return EFI_OUT_OF_RESOURCES;
    125   }
    126   CopyMem (Record, SmbiosEntry, SmbiosEntry->Length);
    127 
    128   if (StringArray != NULL) {
    129     // Append string pack
    130     Str = ((CHAR8 *)Record) + Record->Length;
    131     for (Index = 0; StringArray[Index] != NULL; Index++) {
    132       StringSize = AsciiStrSize (StringArray[Index]);
    133       CopyMem (Str, StringArray[Index], StringSize);
    134       Str += StringSize;
    135     }
    136     *Str = 0;
    137   }
    138 
    139   SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
    140   Status = gSmbios->Add (
    141                      gSmbios,
    142                      gImageHandle,
    143                      &SmbiosHandle,
    144                      Record
    145                      );
    146 
    147   FreePool (Record);
    148   return Status;
    149 }
    150 
    151 
    152 
    153 /**
    154   Update the string associated with an existing SMBIOS record.
    155 
    156   This function allows the update of specific SMBIOS strings. The number of valid strings for any
    157   SMBIOS record is defined by how many strings were present when Add() was called.
    158 
    159   @param[in]    SmbiosHandle    SMBIOS Handle of structure that will have its string updated.
    160   @param[in]    StringNumber    The non-zero string number of the string to update.
    161   @param[in]    String          Update the StringNumber string with String.
    162 
    163   @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
    164   @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid.
    165   @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
    166   @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
    167 **/
    168 EFI_STATUS
    169 EFIAPI
    170 SmbiosLibUpdateString (
    171   IN  EFI_SMBIOS_HANDLE     SmbiosHandle,
    172   IN  SMBIOS_TABLE_STRING   StringNumber,
    173   IN  CHAR8                 *String
    174   )
    175 {
    176   UINTN StringIndex;
    177 
    178   if (String == NULL) {
    179     return EFI_INVALID_PARAMETER;
    180   }
    181 
    182   if (*String == '\0') {
    183     // A string with no data is not legal in SMBIOS
    184     return EFI_INVALID_PARAMETER;
    185   }
    186 
    187   StringIndex = StringNumber;
    188   return gSmbios->UpdateString (gSmbios, &SmbiosHandle, &StringIndex, String);
    189 }
    190 
    191 
    192 /**
    193   Update the string associated with an existing SMBIOS record.
    194 
    195   This function allows the update of specific SMBIOS strings. The number of valid strings for any
    196   SMBIOS record is defined by how many strings were present when Add() was called.
    197 
    198   @param[in]    SmbiosHandle    SMBIOS Handle of structure that will have its string updated.
    199   @param[in]    StringNumber    The non-zero string number of the string to update.
    200   @param[in]    String          Update the StringNumber string with String.
    201 
    202   @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
    203   @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid.
    204   @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
    205   @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
    206 **/
    207 EFI_STATUS
    208 EFIAPI
    209 SmbiosLibUpdateUnicodeString (
    210   IN  EFI_SMBIOS_HANDLE     SmbiosHandle,
    211   IN  SMBIOS_TABLE_STRING   StringNumber,
    212   IN  CHAR16                *String
    213   )
    214 {
    215   EFI_STATUS  Status;
    216   UINTN       StringIndex;
    217   CHAR8       *Ascii;
    218 
    219   if (String == NULL) {
    220     return EFI_INVALID_PARAMETER;
    221   }
    222 
    223   if (*String == '\0') {
    224     // A string with no data is not legal in SMBIOS
    225     return EFI_INVALID_PARAMETER;
    226   }
    227 
    228   Ascii = AllocateZeroPool (StrSize (String));
    229   if (Ascii == NULL) {
    230     return EFI_OUT_OF_RESOURCES;
    231   }
    232   UnicodeStrToAsciiStr (String, Ascii);
    233 
    234   StringIndex = StringNumber;
    235   Status = gSmbios->UpdateString (gSmbios, &SmbiosHandle, &StringIndex, Ascii);
    236 
    237   FreePool (Ascii);
    238   return Status;
    239 }
    240 
    241 
    242 /**
    243   Allow caller to read a specific SMBIOS string
    244 
    245   @param[in]    Header          SMBIOS record that contains the string.
    246   @param[in[    StringNumber    Instance of SMBIOS string 1 - N.
    247 
    248   @retval NULL                  Instance of Type SMBIOS string was not found.
    249   @retval Other                 Pointer to matching SMBIOS string.
    250 **/
    251 CHAR8 *
    252 EFIAPI
    253 SmbiosLibReadString (
    254   IN SMBIOS_STRUCTURE   *Header,
    255   IN EFI_SMBIOS_STRING  StringNumber
    256   )
    257 {
    258   CHAR8       *Data;
    259   UINTN       Match;
    260 
    261   Data = (CHAR8 *)Header + Header->Length;
    262   for (Match = 1;!(*Data == 0 && *(Data+1) == 0); ) {
    263     if (StringNumber == Match) {
    264       return Data;
    265     }
    266     Data++;
    267     if (*(Data - 1) == '\0') {
    268       Match++;
    269     }
    270   }
    271 
    272   return NULL;
    273 }
    274 
    275 
    276 /**
    277   Allow the caller to discover a specific SMBIOS entry, and patch it if necissary.
    278 
    279   @param[in]    Type            Type of the next SMBIOS record to return.
    280   @param[in[    Instance        Instance of SMBIOS record 0 - N-1.
    281   @param[out]   SmbiosHandle    Returns SMBIOS handle for the matching record.
    282 
    283   @retval NULL                  Instance of Type SMBIOS record was not found.
    284   @retval Other                 Pointer to matching SMBIOS record.
    285 **/
    286 SMBIOS_STRUCTURE *
    287 EFIAPI
    288 SmbiosLibGetRecord (
    289   IN  EFI_SMBIOS_TYPE   Type,
    290   IN  UINTN             Instance,
    291   OUT EFI_SMBIOS_HANDLE *SmbiosHandle
    292   )
    293 {
    294   EFI_STATUS              Status;
    295   EFI_SMBIOS_TABLE_HEADER *Record;
    296   UINTN                   Match;
    297 
    298   Match         = 0;
    299   *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
    300   do {
    301     Status = gSmbios->GetNext (gSmbios, SmbiosHandle, &Type, &Record, NULL);
    302     if (!EFI_ERROR (Status)) {
    303       if (Match == Instance) {
    304         return (SMBIOS_STRUCTURE *)Record;
    305       }
    306       Match++;
    307     }
    308   } while (!EFI_ERROR (Status));
    309 
    310   return NULL;
    311 }
    312 
    313 
    314 /**
    315   Remove an SMBIOS record.
    316 
    317   This function removes an SMBIOS record using the handle specified by SmbiosHandle.
    318 
    319   @param[in]    SmbiosHandle        The handle of the SMBIOS record to remove.
    320 
    321   @retval EFI_SUCCESS               SMBIOS record was removed.
    322   @retval EFI_INVALID_PARAMETER     SmbiosHandle does not specify a valid SMBIOS record.
    323 **/
    324 EFI_STATUS
    325 EFIAPI
    326 SmbiosLibRemove (
    327   OUT EFI_SMBIOS_HANDLE SmbiosHandle
    328   )
    329 {
    330   return gSmbios->Remove (gSmbios, SmbiosHandle);
    331 }
    332 
    333 
    334 
    335 /**
    336 
    337   @param  ImageHandle  ImageHandle of the loaded driver.
    338   @param  SystemTable  Pointer to the EFI System Table.
    339 
    340   @retval  EFI_SUCCESS            Register successfully.
    341   @retval  EFI_OUT_OF_RESOURCES   No enough memory to register this handler.
    342 **/
    343 EFI_STATUS
    344 EFIAPI
    345 SmbiosLibConstructor (
    346   IN EFI_HANDLE        ImageHandle,
    347   IN EFI_SYSTEM_TABLE  *SystemTable
    348   )
    349 {
    350   return gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&gSmbios);
    351 }
    352 
    353