1 /** @file
2   API for SMBIOS table.
3 
4   Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 
16 #include "../UefiShellDebug1CommandsLib.h"
17 #include <Guid/SmBios.h>
18 #include "LibSmbiosView.h"
19 #include "SmbiosView.h"
20 
21 STATIC UINT8                    mInit         = 0;
22 STATIC UINT8                    m64Init       = 0;
23 STATIC SMBIOS_TABLE_ENTRY_POINT     *mSmbiosTable   = NULL;
24 STATIC SMBIOS_TABLE_3_0_ENTRY_POINT *mSmbios64BitTable = NULL;
25 STATIC SMBIOS_STRUCTURE_POINTER m_SmbiosStruct;
26 STATIC SMBIOS_STRUCTURE_POINTER *mSmbiosStruct = &m_SmbiosStruct;
27 STATIC SMBIOS_STRUCTURE_POINTER m_Smbios64BitStruct;
28 STATIC SMBIOS_STRUCTURE_POINTER *mSmbios64BitStruct = &m_Smbios64BitStruct;
29 
30 /**
31   Init the SMBIOS VIEW API's environment.
32 
33   @retval EFI_SUCCESS  Successful to init the SMBIOS VIEW Lib.
34 **/
35 EFI_STATUS
LibSmbiosInit(VOID)36 LibSmbiosInit (
37   VOID
38   )
39 {
40   EFI_STATUS  Status;
41 
42   //
43   // Init only once
44   //
45   if (mInit == 1) {
46     return EFI_SUCCESS;
47   }
48   //
49   // Get SMBIOS table from System Configure table
50   //
51   Status = GetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID**)&mSmbiosTable);
52 
53   if (mSmbiosTable == NULL) {
54     return EFI_NOT_FOUND;
55   }
56 
57   if (EFI_ERROR (Status)) {
58     ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR), gShellDebug1HiiHandle, Status);
59     return Status;
60   }
61   //
62   // Init SMBIOS structure table address
63   //
64   mSmbiosStruct->Raw  = (UINT8 *) (UINTN) (mSmbiosTable->TableAddress);
65 
66   mInit               = 1;
67   return EFI_SUCCESS;
68 }
69 
70 /**
71   Init the SMBIOS VIEW API's environment.
72 
73   @retval EFI_SUCCESS  Successful to init the SMBIOS VIEW Lib.
74 **/
75 EFI_STATUS
LibSmbios64BitInit(VOID)76 LibSmbios64BitInit (
77   VOID
78   )
79 {
80   EFI_STATUS  Status;
81 
82   //
83   // Init only once
84   //
85   if (m64Init == 1) {
86     return EFI_SUCCESS;
87   }
88   //
89   // Get SMBIOS table from System Configure table
90   //
91   Status = GetSystemConfigurationTable (&gEfiSmbios3TableGuid, (VOID**)&mSmbios64BitTable);
92 
93   if (mSmbios64BitTable == NULL) {
94     return EFI_NOT_FOUND;
95   }
96 
97   if (EFI_ERROR (Status)) {
98     ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR), gShellDebug1HiiHandle, Status);
99     return Status;
100   }
101   //
102   // Init SMBIOS structure table address
103   //
104   mSmbios64BitStruct->Raw  = (UINT8 *) (UINTN) (mSmbios64BitTable->TableAddress);
105 
106   m64Init               = 1;
107   return EFI_SUCCESS;
108 }
109 
110 /**
111   Cleanup the Smbios information.
112 **/
113 VOID
LibSmbiosCleanup(VOID)114 LibSmbiosCleanup (
115   VOID
116   )
117 {
118   //
119   // Release resources
120   //
121   if (mSmbiosTable != NULL) {
122     mSmbiosTable = NULL;
123   }
124 
125   mInit = 0;
126 }
127 
128 /**
129   Cleanup the Smbios information.
130 **/
131 VOID
LibSmbios64BitCleanup(VOID)132 LibSmbios64BitCleanup (
133   VOID
134   )
135 {
136   //
137   // Release resources
138   //
139   if (mSmbios64BitTable != NULL) {
140     mSmbios64BitTable = NULL;
141   }
142 
143   m64Init = 0;
144 }
145 
146 /**
147   Get the entry point structure for the table.
148 
149   @param[out] EntryPointStructure  The pointer to populate.
150 **/
151 VOID
LibSmbiosGetEPS(OUT SMBIOS_TABLE_ENTRY_POINT ** EntryPointStructure)152 LibSmbiosGetEPS (
153   OUT SMBIOS_TABLE_ENTRY_POINT **EntryPointStructure
154   )
155 {
156   //
157   // return SMBIOS Table address
158   //
159   *EntryPointStructure = mSmbiosTable;
160 }
161 
162 /**
163   Get the entry point structure for the table.
164 
165   @param[out] EntryPointStructure  The pointer to populate.
166 **/
167 VOID
LibSmbios64BitGetEPS(OUT SMBIOS_TABLE_3_0_ENTRY_POINT ** EntryPointStructure)168 LibSmbios64BitGetEPS (
169   OUT SMBIOS_TABLE_3_0_ENTRY_POINT **EntryPointStructure
170   )
171 {
172   //
173   // return SMBIOS Table address
174   //
175   *EntryPointStructure = mSmbios64BitTable;
176 }
177 
178 /**
179   Return SMBIOS string for the given string number.
180 
181   @param[in] Smbios         Pointer to SMBIOS structure.
182   @param[in] StringNumber   String number to return. -1 is used to skip all strings and
183                             point to the next SMBIOS structure.
184 
185   @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == -1
186 **/
187 CHAR8*
LibGetSmbiosString(IN SMBIOS_STRUCTURE_POINTER * Smbios,IN UINT16 StringNumber)188 LibGetSmbiosString (
189   IN  SMBIOS_STRUCTURE_POINTER    *Smbios,
190   IN  UINT16                      StringNumber
191   )
192 {
193   UINT16  Index;
194   CHAR8   *String;
195 
196   ASSERT (Smbios != NULL);
197 
198   //
199   // Skip over formatted section
200   //
201   String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length);
202 
203   //
204   // Look through unformated section
205   //
206   for (Index = 1; Index <= StringNumber; Index++) {
207     if (StringNumber == Index) {
208       return String;
209     }
210     //
211     // Skip string
212     //
213     for (; *String != 0; String++);
214     String++;
215 
216     if (*String == 0) {
217       //
218       // If double NULL then we are done.
219       //  Return pointer to next structure in Smbios.
220       //  if you pass in a -1 you will always get here
221       //
222       Smbios->Raw = (UINT8 *)++String;
223       return NULL;
224     }
225   }
226 
227   return NULL;
228 }
229 
230 /**
231     Get SMBIOS structure for the given Handle,
232     Handle is changed to the next handle or 0xFFFF when the end is
233     reached or the handle is not found.
234 
235     @param[in, out] Handle     0xFFFF: get the first structure
236                                Others: get a structure according to this value.
237     @param[out] Buffer         The pointer to the pointer to the structure.
238     @param[out] Length         Length of the structure.
239 
240     @retval DMI_SUCCESS   Handle is updated with next structure handle or
241                           0xFFFF(end-of-list).
242 
243     @retval DMI_INVALID_HANDLE  Handle is updated with first structure handle or
244                                 0xFFFF(end-of-list).
245 **/
246 EFI_STATUS
LibGetSmbiosStructure(IN OUT UINT16 * Handle,OUT UINT8 ** Buffer,OUT UINT16 * Length)247 LibGetSmbiosStructure (
248   IN  OUT UINT16  *Handle,
249   OUT UINT8       **Buffer,
250   OUT UINT16      *Length
251   )
252 {
253   SMBIOS_STRUCTURE_POINTER  Smbios;
254   SMBIOS_STRUCTURE_POINTER  SmbiosEnd;
255   UINT8                     *Raw;
256 
257   if (*Handle == INVALID_HANDLE) {
258     *Handle = mSmbiosStruct->Hdr->Handle;
259     return DMI_INVALID_HANDLE;
260   }
261 
262   if ((Buffer == NULL) || (Length == NULL)) {
263     ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC), gShellDebug1HiiHandle);
264     return DMI_INVALID_HANDLE;
265   }
266 
267   *Length       = 0;
268   Smbios.Hdr    = mSmbiosStruct->Hdr;
269   SmbiosEnd.Raw = Smbios.Raw + mSmbiosTable->TableLength;
270   while (Smbios.Raw < SmbiosEnd.Raw) {
271     if (Smbios.Hdr->Handle == *Handle) {
272       Raw = Smbios.Raw;
273       //
274       // Walk to next structure
275       //
276       LibGetSmbiosString (&Smbios, (UINT16) (-1));
277       //
278       // Length = Next structure head - this structure head
279       //
280       *Length = (UINT16) (Smbios.Raw - Raw);
281       *Buffer = Raw;
282       //
283       // update with the next structure handle.
284       //
285       if (Smbios.Raw < SmbiosEnd.Raw) {
286         *Handle = Smbios.Hdr->Handle;
287       } else {
288         *Handle = INVALID_HANDLE;
289       }
290       return DMI_SUCCESS;
291     }
292     //
293     // Walk to next structure
294     //
295     LibGetSmbiosString (&Smbios, (UINT16) (-1));
296   }
297 
298   *Handle = INVALID_HANDLE;
299   return DMI_INVALID_HANDLE;
300 }
301 
302 /**
303     Get SMBIOS structure for the given Handle,
304     Handle is changed to the next handle or 0xFFFF when the end is
305     reached or the handle is not found.
306 
307     @param[in, out] Handle     0xFFFF: get the first structure
308                                Others: get a structure according to this value.
309     @param[out] Buffer         The pointer to the pointer to the structure.
310     @param[out] Length         Length of the structure.
311 
312     @retval DMI_SUCCESS   Handle is updated with next structure handle or
313                           0xFFFF(end-of-list).
314 
315     @retval DMI_INVALID_HANDLE  Handle is updated with first structure handle or
316                                 0xFFFF(end-of-list).
317 **/
318 EFI_STATUS
LibGetSmbios64BitStructure(IN OUT UINT16 * Handle,OUT UINT8 ** Buffer,OUT UINT16 * Length)319 LibGetSmbios64BitStructure (
320   IN  OUT UINT16  *Handle,
321   OUT UINT8       **Buffer,
322   OUT UINT16      *Length
323   )
324 {
325   SMBIOS_STRUCTURE_POINTER  Smbios;
326   SMBIOS_STRUCTURE_POINTER  SmbiosEnd;
327   UINT8                     *Raw;
328 
329   if (*Handle == INVALID_HANDLE) {
330     *Handle = mSmbios64BitStruct->Hdr->Handle;
331     return DMI_INVALID_HANDLE;
332   }
333 
334   if ((Buffer == NULL) || (Length == NULL)) {
335     ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC), gShellDebug1HiiHandle);
336     return DMI_INVALID_HANDLE;
337   }
338 
339   *Length     = 0;
340   Smbios.Hdr  = mSmbios64BitStruct->Hdr;
341 
342   SmbiosEnd.Raw = Smbios.Raw + mSmbios64BitTableLength;
343   while (Smbios.Raw < SmbiosEnd.Raw) {
344     if (Smbios.Hdr->Handle == *Handle) {
345       Raw = Smbios.Raw;
346       //
347       // Walk to next structure
348       //
349       LibGetSmbiosString (&Smbios, (UINT16) (-1));
350       //
351       // Length = Next structure head - this structure head
352       //
353       *Length = (UINT16) (Smbios.Raw - Raw);
354       *Buffer = Raw;
355       //
356       // update with the next structure handle.
357       //
358       if (Smbios.Raw < SmbiosEnd.Raw) {
359         *Handle = Smbios.Hdr->Handle;
360       } else {
361         *Handle = INVALID_HANDLE;
362       }
363       return DMI_SUCCESS;
364     }
365     //
366     // Walk to next structure
367     //
368     LibGetSmbiosString (&Smbios, (UINT16) (-1));
369   }
370 
371   *Handle = INVALID_HANDLE;
372   return DMI_INVALID_HANDLE;
373 }
374