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