1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
|
/** @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 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#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;
}
UnicodeStrToAsciiStrS (String, Ascii, StrSize (String));
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);
}
|