SmbiosLib.c 9.6 KB

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