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