• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
SmbiosLibInitializeFromTemplate(IN SMBIOS_TEMPLATE_ENTRY * Template)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
SmbiosLibCreateEntry(IN SMBIOS_STRUCTURE * SmbiosEntry,IN CHAR8 ** StringArray)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
SmbiosLibUpdateString(IN EFI_SMBIOS_HANDLE SmbiosHandle,IN SMBIOS_TABLE_STRING StringNumber,IN CHAR8 * String)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
SmbiosLibUpdateUnicodeString(IN EFI_SMBIOS_HANDLE SmbiosHandle,IN SMBIOS_TABLE_STRING StringNumber,IN CHAR16 * String)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
SmbiosLibReadString(IN SMBIOS_STRUCTURE * Header,IN EFI_SMBIOS_STRING StringNumber)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
SmbiosLibGetRecord(IN EFI_SMBIOS_TYPE Type,IN UINTN Instance,OUT EFI_SMBIOS_HANDLE * SmbiosHandle)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
SmbiosLibRemove(OUT EFI_SMBIOS_HANDLE SmbiosHandle)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
SmbiosLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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