]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
Fix the incorrect usage for PCD PcdResetOnMemoryTypeInformationChange in Duet, Unix...
[mirror_edk2.git] / MdeModulePkg / Universal / SmbiosDxe / SmbiosDxe.c
CommitLineData
310b04e6 1/** @file\r
2 This code produces the Smbios protocol. It also responsible for constructing \r
3 SMBIOS table into system table.\r
4 \r
afe3969c 5Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 6This program and the accompanying materials \r
310b04e6 7are licensed and made available under the terms and conditions of the BSD License \r
8which accompanies this distribution. The full text of the license may be found at \r
9http://opensource.org/licenses/bsd-license.php \r
10 \r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include "SmbiosDxe.h"\r
17\r
18//\r
19// Module Global:\r
20// Since this driver will only ever produce one instance of the\r
21// protocol you are not required to dynamically allocate the PrivateData.\r
22//\r
23SMBIOS_INSTANCE mPrivateData;\r
24\r
25//\r
26// Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.\r
27//\r
28SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure = NULL;\r
29SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {\r
30 //\r
31 // AnchorString\r
32 //\r
33 {\r
34 0x5f,\r
35 0x53,\r
36 0x4d,\r
37 0x5f\r
38 },\r
39 //\r
40 // EntryPointStructureChecksum,TO BE FILLED\r
41 //\r
42 0,\r
43 //\r
44 // EntryPointStructure Length\r
45 //\r
46 0x1f,\r
47 //\r
9f7d5b46 48 // MajorVersion\r
310b04e6 49 //\r
9f7d5b46 50 (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) >> 8),\r
310b04e6 51 //\r
9f7d5b46 52 // MinorVersion\r
310b04e6 53 //\r
9f7d5b46 54 (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) & 0x00ff),\r
310b04e6 55 //\r
56 // MaxStructureSize, TO BE FILLED\r
57 //\r
58 0,\r
59 //\r
60 // EntryPointRevision\r
61 //\r
62 0,\r
63 //\r
64 // FormattedArea\r
65 //\r
66 {\r
67 0,\r
68 0,\r
69 0,\r
70 0,\r
71 0\r
72 },\r
73 //\r
74 // IntermediateAnchorString\r
75 //\r
76 {\r
77 0x5f,\r
78 0x44,\r
79 0x4d,\r
80 0x49,\r
81 0x5f\r
82 },\r
83 //\r
84 // IntermediateChecksum, TO BE FILLED\r
85 //\r
86 0,\r
87 //\r
88 // StructureTableLength, TO BE FILLED\r
89 //\r
90 0,\r
91 //\r
92 // StructureTableAddress, TO BE FILLED\r
93 //\r
94 0,\r
95 //\r
96 // NumberOfSmbiosStructures, TO BE FILLED\r
97 //\r
98 0,\r
99 //\r
100 // SmbiosBcdRevision\r
101 //\r
102 0 \r
103};\r
104\r
105\r
106/**\r
107\r
0ddd8553 108 Get the full size of SMBIOS structure including optional strings that follow the formatted structure.\r
310b04e6 109\r
afe3969c 110 @param This The EFI_SMBIOS_PROTOCOL instance.\r
0ddd8553 111 @param Head Pointer to the beginning of SMBIOS structure.\r
310b04e6 112 @param Size The returned size.\r
113 @param NumberOfStrings The returned number of optional strings that follow the formatted structure.\r
114\r
115 @retval EFI_SUCCESS Size retured in Size.\r
0ddd8553 116 @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.\r
310b04e6 117 \r
118**/\r
119EFI_STATUS\r
120EFIAPI\r
121GetSmbiosStructureSize (\r
afe3969c 122 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
310b04e6 123 IN EFI_SMBIOS_TABLE_HEADER *Head,\r
124 OUT UINTN *Size,\r
125 OUT UINTN *NumberOfStrings\r
126 )\r
127{\r
128 UINTN FullSize;\r
129 UINT8 StrLen;\r
130 INT8* CharInStr;\r
131 \r
132 if (Size == NULL || NumberOfStrings == NULL) {\r
133 return EFI_INVALID_PARAMETER;\r
134 }\r
135\r
136 FullSize = Head->Length;\r
137 CharInStr = (INT8*)Head + Head->Length;\r
138 *Size = FullSize;\r
139 *NumberOfStrings = 0;\r
140 StrLen = 0;\r
141 //\r
142 // look for the two consecutive zeros, check the string limit by the way.\r
143 //\r
144 while (*CharInStr != 0 || *(CharInStr+1) != 0) { \r
145 if (*CharInStr == 0) {\r
310b04e6 146 *Size += 1;\r
147 CharInStr++;\r
148 }\r
149\r
afe3969c
SZ
150 if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)){\r
151 for (StrLen = 0 ; StrLen < SMBIOS_STRING_MAX_LENGTH; StrLen++) {\r
152 if (*(CharInStr+StrLen) == 0) {\r
153 break;\r
154 }\r
155 }\r
310b04e6 156\r
afe3969c
SZ
157 if (StrLen == SMBIOS_STRING_MAX_LENGTH) {\r
158 return EFI_INVALID_PARAMETER;\r
159 }\r
160 } else {\r
161 //\r
162 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string\r
163 //\r
164 for (StrLen = 0 ;; StrLen++) {\r
165 if (*(CharInStr+StrLen) == 0) {\r
166 break;\r
167 }\r
168 }\r
310b04e6 169 }\r
afe3969c 170\r
310b04e6 171 //\r
172 // forward the pointer\r
173 //\r
174 CharInStr += StrLen;\r
175 *Size += StrLen;\r
310b04e6 176 *NumberOfStrings += 1;\r
177 }\r
f8ee20c9 178\r
310b04e6 179 //\r
180 // count ending two zeros.\r
181 //\r
182 *Size += 2;\r
afe3969c 183 return EFI_SUCCESS;\r
310b04e6 184}\r
185\r
186/**\r
187\r
188 Determin whether an SmbiosHandle has already in use.\r
189\r
0ddd8553 190 @param Head Pointer to the beginning of SMBIOS structure.\r
310b04e6 191 @param Handle A unique handle will be assigned to the SMBIOS record.\r
192\r
193 @retval TRUE Smbios handle already in use.\r
194 @retval FALSE Smbios handle is NOT used.\r
195 \r
196**/\r
197BOOLEAN\r
198EFIAPI\r
199CheckSmbiosHandleExistance (\r
200 IN LIST_ENTRY *Head,\r
201 IN EFI_SMBIOS_HANDLE Handle\r
202 )\r
203{\r
204 LIST_ENTRY *Link;\r
205 SMBIOS_HANDLE_ENTRY *HandleEntry;\r
206 \r
207 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
208 HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link);\r
209 if (HandleEntry->SmbiosHandle == Handle) {\r
210 return TRUE;\r
211 }\r
212 }\r
213\r
214 return FALSE;\r
215}\r
216\r
217/**\r
218\r
219 Get the max SmbiosHandle that could be use.\r
220\r
221 @param This The EFI_SMBIOS_PROTOCOL instance.\r
222 @param MaxHandle The max handle that could be assigned to the SMBIOS record.\r
223\r
224**/\r
225VOID\r
226EFIAPI\r
227GetMaxSmbiosHandle (\r
228 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
229 IN OUT EFI_SMBIOS_HANDLE *MaxHandle\r
230 ) \r
231{\r
232 if (This->MajorVersion == 2 && This->MinorVersion == 0) {\r
233 *MaxHandle = 0xFFFE;\r
234 } else {\r
235 *MaxHandle = 0xFEFF;\r
236 }\r
237}\r
238\r
239/**\r
240\r
241 Get an SmbiosHandle that could use.\r
242\r
243 @param This The EFI_SMBIOS_PROTOCOL instance.\r
244 @param SmbiosHandle A unique handle will be assigned to the SMBIOS record.\r
245\r
246 @retval EFI_SUCCESS Smbios handle got.\r
247 @retval EFI_OUT_OF_RESOURCES Smbios handle is NOT available.\r
248 \r
249**/\r
250EFI_STATUS\r
251EFIAPI\r
252GetAvailableSmbiosHandle (\r
253 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
254 IN OUT EFI_SMBIOS_HANDLE *Handle\r
255 )\r
256{\r
257 LIST_ENTRY *Head;\r
258 SMBIOS_INSTANCE *Private;\r
259 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
260 EFI_SMBIOS_HANDLE AvailableHandle;\r
261\r
262 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
263\r
264 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
265 Head = &Private->AllocatedHandleListHead;\r
266 for (AvailableHandle = 1; AvailableHandle < MaxSmbiosHandle; AvailableHandle++) {\r
267 if (!CheckSmbiosHandleExistance(Head, AvailableHandle)) {\r
268 *Handle = AvailableHandle;\r
269 return EFI_SUCCESS;\r
270 }\r
271 }\r
272\r
273 return EFI_OUT_OF_RESOURCES;\r
274}\r
275\r
276\r
277/**\r
278 Add an SMBIOS record.\r
279\r
280 @param This The EFI_SMBIOS_PROTOCOL instance.\r
281 @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL\r
282 means no handle.\r
283 @param SmbiosHandle On entry, if non-zero, the handle of the SMBIOS record. If zero, then a unique handle\r
284 will be assigned to the SMBIOS record. If the SMBIOS handle is already in use\r
285 EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.\r
286 @param Record The data for the fixed portion of the SMBIOS record. The format of the record is\r
287 determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined \r
288 by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or \r
289 a set of null terminated strings and a null.\r
290\r
291 @retval EFI_SUCCESS Record was added.\r
292 @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.\r
293 @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use.\r
294\r
295**/\r
296EFI_STATUS\r
297EFIAPI\r
298SmbiosAdd (\r
299 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
300 IN EFI_HANDLE ProducerHandle, OPTIONAL\r
301 IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle,\r
302 IN EFI_SMBIOS_TABLE_HEADER *Record\r
303 )\r
304{\r
305 VOID *Raw;\r
306 UINTN TotalSize;\r
307 UINTN RecordSize;\r
308 UINTN StructureSize;\r
309 UINTN NumberOfStrings;\r
310 EFI_STATUS Status;\r
311 LIST_ENTRY *Head;\r
312 SMBIOS_INSTANCE *Private;\r
313 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
314 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
315 SMBIOS_HANDLE_ENTRY *HandleEntry;\r
316 EFI_SMBIOS_RECORD_HEADER *InternalRecord;\r
317 \r
318 if (SmbiosHandle == NULL) {\r
319 return EFI_INVALID_PARAMETER;\r
320 }\r
321 \r
322 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
323 //\r
324 // Check whether SmbiosHandle is already in use\r
325 //\r
326 Head = &Private->AllocatedHandleListHead;\r
327 if (*SmbiosHandle != 0 && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) {\r
328 return EFI_ALREADY_STARTED;\r
329 }\r
330\r
331 //\r
332 // when SmbiosHandle is zero, an available handle will be assigned\r
333 //\r
334 if (*SmbiosHandle == 0) {\r
335 Status = GetAvailableSmbiosHandle(This, SmbiosHandle);\r
336 if (EFI_ERROR(Status)) {\r
337 return Status;\r
338 }\r
339 } else {\r
340 //\r
341 // Check this handle validity\r
342 //\r
343 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
344 if (*SmbiosHandle > MaxSmbiosHandle) {\r
345 return EFI_INVALID_PARAMETER;\r
346 }\r
347 }\r
348\r
349 //\r
350 // Calculate record size and string number\r
351 //\r
afe3969c 352 Status = GetSmbiosStructureSize(This, Record, &StructureSize, &NumberOfStrings);\r
310b04e6 353 if (EFI_ERROR(Status)) {\r
354 return Status;\r
355 }\r
356\r
357 //\r
358 // Enter into critical section\r
359 // \r
360 Status = EfiAcquireLockOrFail (&Private->DataLock);\r
361 if (EFI_ERROR (Status)) {\r
362 return Status;\r
363 }\r
364 \r
365 RecordSize = sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize;\r
366 TotalSize = sizeof (EFI_SMBIOS_ENTRY) + RecordSize;\r
367\r
368 //\r
369 // Allocate internal buffer\r
370 //\r
0d34b1cf 371 SmbiosEntry = AllocateZeroPool (TotalSize);\r
310b04e6 372 if (SmbiosEntry == NULL) {\r
373 EfiReleaseLock (&Private->DataLock);\r
374 return EFI_OUT_OF_RESOURCES;\r
375 }\r
0d34b1cf 376 HandleEntry = AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY));\r
310b04e6 377 if (HandleEntry == NULL) {\r
378 EfiReleaseLock (&Private->DataLock);\r
379 return EFI_OUT_OF_RESOURCES;\r
380 }\r
381\r
382 //\r
383 // Build Handle Entry and insert into linked list\r
384 //\r
310b04e6 385 HandleEntry->Signature = SMBIOS_HANDLE_ENTRY_SIGNATURE;\r
386 HandleEntry->SmbiosHandle = *SmbiosHandle;\r
387 InsertTailList(&Private->AllocatedHandleListHead, &HandleEntry->Link);\r
388\r
310b04e6 389 InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (SmbiosEntry + 1);\r
390 Raw = (VOID *) (InternalRecord + 1);\r
391\r
392 //\r
393 // Build internal record Header\r
394 //\r
395 InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION;\r
c9325700 396 InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER);\r
310b04e6 397 InternalRecord->RecordSize = RecordSize;\r
398 InternalRecord->ProducerHandle = ProducerHandle;\r
399 InternalRecord->NumberOfStrings = NumberOfStrings;\r
400 //\r
401 // Insert record into the internal linked list\r
402 //\r
403 SmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE;\r
404 SmbiosEntry->RecordHeader = InternalRecord;\r
405 SmbiosEntry->RecordSize = TotalSize;\r
406 InsertTailList (&Private->DataListHead, &SmbiosEntry->Link);\r
407\r
408 CopyMem (Raw, Record, StructureSize);\r
409 ((EFI_SMBIOS_TABLE_HEADER*)Raw)->Handle = *SmbiosHandle;\r
410\r
0ddd8553 411 //\r
412 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
413 // Here we create SMBIOS table and publish it in\r
414 // configuration table, so other UEFI drivers can get SMBIOS table from\r
415 // configuration table without depending on PI SMBIOS protocol.\r
416 //\r
417 SmbiosTableConstruction ();\r
418 \r
310b04e6 419 //\r
420 // Leave critical section\r
421 //\r
422 EfiReleaseLock (&Private->DataLock);\r
423 return EFI_SUCCESS;\r
424}\r
425\r
426/**\r
427 Update the string associated with an existing SMBIOS record.\r
428\r
429 @param This The EFI_SMBIOS_PROTOCOL instance.\r
430 @param SmbiosHandle SMBIOS Handle of structure that will have its string updated.\r
431 @param StringNumber The non-zero string number of the string to update\r
432 @param String Update the StringNumber string with String.\r
433\r
434 @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated.\r
435 @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.\r
436 @retval EFI_UNSUPPORTED String was not added since it's longer than 64 significant characters.\r
437 @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record.\r
438\r
439**/\r
440EFI_STATUS\r
441EFIAPI\r
442SmbiosUpdateString (\r
443 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
444 IN EFI_SMBIOS_HANDLE *SmbiosHandle,\r
445 IN UINTN *StringNumber,\r
446 IN CHAR8 *String\r
447 )\r
448{\r
449 UINTN InputStrLen;\r
450 UINTN TargetStrLen;\r
451 UINTN StrIndex;\r
452 UINTN TargetStrOffset;\r
453 UINTN NewEntrySize;\r
454 CHAR8 *StrStart;\r
455 VOID *Raw;\r
456 LIST_ENTRY *Link;\r
457 LIST_ENTRY *Head;\r
458 EFI_STATUS Status;\r
459 SMBIOS_INSTANCE *Private;\r
460 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
461 EFI_SMBIOS_ENTRY *ResizedSmbiosEntry;\r
462 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
463 EFI_SMBIOS_TABLE_HEADER *Record;\r
464 EFI_SMBIOS_RECORD_HEADER *InternalRecord;\r
465 \r
466 //\r
467 // Check args validity\r
468 //\r
469 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
470\r
471 if (*SmbiosHandle > MaxSmbiosHandle) {\r
472 return EFI_INVALID_PARAMETER;\r
473 }\r
474\r
475 if (String == NULL) {\r
476 return EFI_ABORTED;\r
477 }\r
478\r
479 if (*StringNumber == 0) {\r
480 return EFI_NOT_FOUND;\r
481 }\r
482\r
483 InputStrLen = AsciiStrLen(String);\r
afe3969c
SZ
484\r
485 //\r
486 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string\r
487 //\r
488 if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) {\r
489 if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
490 return EFI_UNSUPPORTED;\r
491 }\r
310b04e6 492 }\r
493\r
494 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
495 //\r
496 // Enter into critical section\r
497 // \r
498 Status = EfiAcquireLockOrFail (&Private->DataLock);\r
499 if (EFI_ERROR (Status)) {\r
500 return Status;\r
501 }\r
502\r
503 Head = &Private->DataListHead;\r
504 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
505 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
506 Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
507\r
afe3969c 508 if (Record->Handle == *SmbiosHandle) {\r
310b04e6 509 //\r
0ddd8553 510 // Find out the specified SMBIOS record\r
310b04e6 511 //\r
512 if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) {\r
513 EfiReleaseLock (&Private->DataLock);\r
514 return EFI_NOT_FOUND;\r
515 }\r
516 //\r
517 // Point to unformed string section\r
518 //\r
afe3969c 519 StrStart = (CHAR8 *) Record + Record->Length;\r
310b04e6 520 \r
521 for (StrIndex = 1, TargetStrOffset = 0; StrIndex < *StringNumber; StrStart++, TargetStrOffset++) {\r
522 //\r
523 // A string ends in 00h\r
524 //\r
525 if (*StrStart == 0) {\r
526 StrIndex++;\r
527 }\r
528 \r
529 //\r
530 // String section ends in double-null (0000h)\r
531 //\r
532 if (*StrStart == 0 && *(StrStart + 1) == 0) {\r
533 EfiReleaseLock (&Private->DataLock);\r
534 return EFI_NOT_FOUND;\r
535 } \r
536 }\r
537\r
f8ee20c9 538 if (*StrStart == 0) {\r
afe3969c
SZ
539 StrStart++;\r
540 TargetStrOffset++;\r
f8ee20c9 541 }\r
542 \r
310b04e6 543 //\r
544 // Now we get the string target\r
545 //\r
546 TargetStrLen = AsciiStrLen(StrStart);\r
547 if (InputStrLen == TargetStrLen) {\r
548 AsciiStrCpy(StrStart, String);\r
0ddd8553 549 //\r
550 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
551 // Here we create SMBIOS table and publish it in\r
552 // configuration table, so other UEFI drivers can get SMBIOS table from\r
553 // configuration table without depending on PI SMBIOS protocol.\r
554 //\r
555 SmbiosTableConstruction ();\r
310b04e6 556 EfiReleaseLock (&Private->DataLock);\r
557 return EFI_SUCCESS;\r
558 }\r
559\r
560 //\r
561 // Original string buffer size is not exactly match input string length.\r
562 // Re-allocate buffer is needed.\r
563 //\r
564 NewEntrySize = SmbiosEntry->RecordSize + InputStrLen - TargetStrLen;\r
0d34b1cf 565 ResizedSmbiosEntry = AllocateZeroPool (NewEntrySize);\r
310b04e6 566\r
567 if (ResizedSmbiosEntry == NULL) {\r
568 EfiReleaseLock (&Private->DataLock);\r
569 return EFI_OUT_OF_RESOURCES;\r
570 }\r
571\r
310b04e6 572 InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (ResizedSmbiosEntry + 1);\r
573 Raw = (VOID *) (InternalRecord + 1);\r
574\r
575 //\r
576 // Build internal record Header\r
577 //\r
578 InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION;\r
c9325700 579 InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER);\r
310b04e6 580 InternalRecord->RecordSize = SmbiosEntry->RecordHeader->RecordSize + InputStrLen - TargetStrLen;\r
581 InternalRecord->ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r
582 InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings;\r
583\r
584 //\r
0ddd8553 585 // Copy SMBIOS structure and optional strings.\r
310b04e6 586 //\r
f8ee20c9 587 CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset);\r
588 CopyMem ((VOID*)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1);\r
589 CopyMem ((CHAR8*)((UINTN)Raw + Record->Length + TargetStrOffset + InputStrLen + 1),\r
590 (CHAR8*)Record + Record->Length + TargetStrOffset + TargetStrLen + 1,\r
591 SmbiosEntry->RecordHeader->RecordSize - sizeof (EFI_SMBIOS_RECORD_HEADER) - Record->Length - TargetStrOffset - TargetStrLen - 1);\r
310b04e6 592\r
593 //\r
594 // Insert new record\r
595 //\r
596 ResizedSmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE;\r
597 ResizedSmbiosEntry->RecordHeader = InternalRecord;\r
598 ResizedSmbiosEntry->RecordSize = NewEntrySize;\r
599 InsertTailList (Link->ForwardLink, &ResizedSmbiosEntry->Link);\r
600\r
601 //\r
602 // Remove old record\r
603 //\r
604 RemoveEntryList(Link);\r
605 FreePool(SmbiosEntry);\r
0ddd8553 606 //\r
607 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
608 // Here we create SMBIOS table and publish it in\r
609 // configuration table, so other UEFI drivers can get SMBIOS table from\r
610 // configuration table without depending on PI SMBIOS protocol.\r
611 //\r
612 SmbiosTableConstruction ();\r
310b04e6 613 EfiReleaseLock (&Private->DataLock);\r
614 return EFI_SUCCESS;\r
615 }\r
616 }\r
617\r
618 EfiReleaseLock (&Private->DataLock);\r
619 return EFI_INVALID_PARAMETER;\r
620}\r
621\r
622/**\r
623 Remove an SMBIOS record.\r
624\r
625 @param This The EFI_SMBIOS_PROTOCOL instance.\r
626 @param SmbiosHandle The handle of the SMBIOS record to remove.\r
627\r
628 @retval EFI_SUCCESS SMBIOS record was removed.\r
629 @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record.\r
630\r
631**/\r
632EFI_STATUS\r
633EFIAPI\r
634SmbiosRemove (\r
635 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
636 IN EFI_SMBIOS_HANDLE SmbiosHandle\r
637 )\r
638{\r
639 LIST_ENTRY *Link;\r
640 LIST_ENTRY *Head;\r
641 EFI_STATUS Status;\r
642 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
643 SMBIOS_INSTANCE *Private;\r
644 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
645 SMBIOS_HANDLE_ENTRY *HandleEntry;\r
646 EFI_SMBIOS_TABLE_HEADER *Record;\r
647\r
648 //\r
649 // Check args validity\r
650 //\r
651 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
652\r
653 if (SmbiosHandle > MaxSmbiosHandle) {\r
654 return EFI_INVALID_PARAMETER;\r
655 }\r
656\r
657 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
658 //\r
659 // Enter into critical section\r
660 // \r
661 Status = EfiAcquireLockOrFail (&Private->DataLock);\r
662 if (EFI_ERROR (Status)) {\r
663 return Status;\r
664 }\r
665\r
666 Head = &Private->DataListHead;\r
667 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
668 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
669 Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
afe3969c 670 if (Record->Handle == SmbiosHandle) {\r
310b04e6 671 //\r
672 // Remove specified smobios record from DataList\r
673 //\r
674 RemoveEntryList(Link);\r
675 FreePool(SmbiosEntry);\r
676 // \r
677 // Remove this handle from AllocatedHandleList\r
678 //\r
679 Head = &Private->AllocatedHandleListHead;\r
680 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
681 HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link);\r
afe3969c 682 if (HandleEntry->SmbiosHandle == SmbiosHandle) {\r
310b04e6 683 RemoveEntryList(Link);\r
684 FreePool(HandleEntry);\r
685 break;\r
686 }\r
687 }\r
0ddd8553 688 //\r
689 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
690 // Here we create SMBIOS table and publish it in\r
691 // configuration table, so other UEFI drivers can get SMBIOS table from\r
692 // configuration table without depending on PI SMBIOS protocol.\r
693 //\r
694 SmbiosTableConstruction ();\r
310b04e6 695 EfiReleaseLock (&Private->DataLock);\r
696 return EFI_SUCCESS;\r
697 }\r
698 }\r
699\r
700 //\r
701 // Leave critical section\r
702 //\r
703 EfiReleaseLock (&Private->DataLock);\r
704 return EFI_INVALID_PARAMETER;\r
705 \r
706}\r
707\r
708/**\r
709 Allow the caller to discover all or some of the SMBIOS records.\r
710\r
711 @param This The EFI_SMBIOS_PROTOCOL instance.\r
712 @param SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the\r
713 next SMBIOS record handle. If it is zero on entry, then the first SMBIOS record\r
714 handle will be returned. If it returns zero on exit, then there are no more SMBIOS records.\r
715 @param Type On entry it means return the next SMBIOS record of type Type. If a NULL is passed in \r
716 this functionally it ignored. Type is not modified by the GetNext() function.\r
717 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by\r
718 the unformatted area. The unformatted area optionally contains text strings.\r
719 @param ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned. \r
720 If a NULL pointer is passed in no data will be returned \r
721 \r
722 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.\r
310b04e6 723 @retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.\r
724\r
725**/\r
726EFI_STATUS\r
727EFIAPI\r
728SmbiosGetNext (\r
729 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
730 IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle,\r
731 IN EFI_SMBIOS_TYPE *Type, OPTIONAL\r
732 OUT EFI_SMBIOS_TABLE_HEADER **Record,\r
733 OUT EFI_HANDLE *ProducerHandle OPTIONAL\r
734 )\r
735{\r
736 BOOLEAN StartPointFound;\r
737 LIST_ENTRY *Link;\r
738 LIST_ENTRY *Head;\r
739 SMBIOS_INSTANCE *Private;\r
740 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
741 EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;\r
742\r
743 if (SmbiosHandle == NULL) {\r
744 return EFI_INVALID_PARAMETER;\r
745 }\r
746\r
747 StartPointFound = FALSE;\r
748 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
749 Head = &Private->DataListHead;\r
750 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
751 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
752 SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); \r
753\r
754 //\r
755 // If SmbiosHandle is zero, the first matched SMBIOS record handle will be returned\r
756 //\r
757 if (*SmbiosHandle == 0) {\r
758 if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r
759 continue; \r
760 }\r
761\r
762 *SmbiosHandle = SmbiosTableHeader->Handle;\r
763 *Record =SmbiosTableHeader;\r
764 if (ProducerHandle != NULL) {\r
765 *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r
766 }\r
767 return EFI_SUCCESS;\r
768 }\r
769\r
770 //\r
0ddd8553 771 // Start this round search from the next SMBIOS handle\r
310b04e6 772 //\r
773 if (!StartPointFound && (*SmbiosHandle == SmbiosTableHeader->Handle)) {\r
774 StartPointFound = TRUE;\r
775 continue;\r
776 }\r
777\r
778 if (StartPointFound) {\r
779 if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r
780 continue; \r
781 }\r
782 \r
783 *SmbiosHandle = SmbiosTableHeader->Handle;\r
784 *Record = SmbiosTableHeader; \r
785 if (ProducerHandle != NULL) {\r
786 *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r
787 }\r
788\r
789 return EFI_SUCCESS; \r
790 }\r
791 }\r
792\r
793 *SmbiosHandle = 0;\r
794 return EFI_NOT_FOUND;\r
795 \r
796}\r
797\r
0ddd8553 798/**\r
799 Allow the caller to discover all of the SMBIOS records.\r
800\r
801 @param This The EFI_SMBIOS_PROTOCOL instance.\r
802 @param CurrentSmbiosEntry On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information. \r
803 If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned. \r
804 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by\r
805 the unformatted area. The unformatted area optionally contains text strings.\r
806 \r
807 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.\r
808 *CurrentSmbiosEntry points to the SMBIOS entry which includes the returned SMBIOS record information.\r
809 @retval EFI_NOT_FOUND There is no more SMBIOS entry.\r
810\r
811**/\r
812EFI_STATUS\r
813EFIAPI\r
814GetNextSmbiosRecord (\r
815 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
816 IN OUT EFI_SMBIOS_ENTRY **CurrentSmbiosEntry,\r
817 OUT EFI_SMBIOS_TABLE_HEADER **Record\r
818 )\r
819{\r
820 LIST_ENTRY *Link;\r
821 LIST_ENTRY *Head;\r
822 SMBIOS_INSTANCE *Private;\r
823 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
824 EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;\r
825\r
826 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
827 if (*CurrentSmbiosEntry == NULL) {\r
828 //\r
829 // Get the beginning of SMBIOS entry.\r
830 //\r
831 Head = &Private->DataListHead;\r
832 } else {\r
833 //\r
834 // Get previous SMBIOS entry and make it as start point.\r
835 //\r
836 Head = &(*CurrentSmbiosEntry)->Link;\r
837 }\r
838 \r
839 Link = Head->ForwardLink;\r
840 \r
841 if (Link == &Private->DataListHead) {\r
842 //\r
843 // If no more SMBIOS entry in the list, return not found.\r
844 //\r
845 return EFI_NOT_FOUND;\r
846 }\r
847 \r
848 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
849 SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
850 *Record = SmbiosTableHeader; \r
851 *CurrentSmbiosEntry = SmbiosEntry;\r
852 return EFI_SUCCESS; \r
853}\r
310b04e6 854\r
855/**\r
0ddd8553 856 Assembles SMBIOS table from the SMBIOS protocol. Produce Table\r
310b04e6 857 Entry Point and return the pointer to it.\r
858 \r
859 @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.\r
860 \r
861 @retval EFI_SUCCESS Structure created sucessfully.\r
862 @retval EFI_NOT_READY Some of The SMBIOS records was not available yet.\r
863 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
864 \r
865**/\r
866EFI_STATUS\r
867EFIAPI\r
868SmbiosCreateTable (\r
869 OUT VOID **TableEntryPointStructure\r
870 )\r
871{\r
310b04e6 872 UINT8 *BufferPointer;\r
310b04e6 873 UINTN RecordSize;\r
874 UINTN NumOfStr;\r
875 EFI_STATUS Status;\r
876 EFI_SMBIOS_HANDLE SmbiosHandle;\r
877 EFI_SMBIOS_PROTOCOL *SmbiosProtocol;\r
878 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
879 EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;\r
880 EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure;\r
0ddd8553 881 EFI_SMBIOS_ENTRY *CurrentSmbiosEntry;\r
882 UINTN PreAllocatedPages;\r
310b04e6 883 \r
884 Status = EFI_SUCCESS;\r
885 BufferPointer = NULL;\r
310b04e6 886\r
887 //\r
0ddd8553 888 // Get Smbios protocol to traverse SMBIOS records.\r
310b04e6 889 //\r
0ddd8553 890 SmbiosProtocol = &mPrivateData.Smbios;\r
310b04e6 891\r
0ddd8553 892 PreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
310b04e6 893\r
894 //\r
895 // Make some statistics about all the structures\r
896 //\r
897 EntryPointStructure->NumberOfSmbiosStructures = 0;\r
898 EntryPointStructure->TableLength = 0;\r
899 EntryPointStructure->MaxStructureSize = 0;\r
310b04e6 900\r
901 //\r
902 // Calculate EPS Table Length\r
903 //\r
0ddd8553 904 CurrentSmbiosEntry = NULL;\r
310b04e6 905 do {\r
0ddd8553 906 Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
310b04e6 907 \r
908 if (Status == EFI_SUCCESS) {\r
afe3969c 909 GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
310b04e6 910 //\r
911 // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize\r
912 //\r
afe3969c 913 EntryPointStructure->NumberOfSmbiosStructures++;\r
310b04e6 914 EntryPointStructure->TableLength = (UINT16) (EntryPointStructure->TableLength + RecordSize);\r
915 if (RecordSize > EntryPointStructure->MaxStructureSize) {\r
916 EntryPointStructure->MaxStructureSize = (UINT16) RecordSize;\r
917 }\r
918 }\r
919 } while (!EFI_ERROR(Status));\r
920 \r
921 //\r
922 // Create End-Of-Table structure\r
923 //\r
924 GetMaxSmbiosHandle(SmbiosProtocol, &SmbiosHandle);\r
925 EndStructure.Header.Type = EFI_SMBIOS_TYPE_END_OF_TABLE;\r
c9325700 926 EndStructure.Header.Length = (UINT8) sizeof (EFI_SMBIOS_TABLE_HEADER);\r
310b04e6 927 EndStructure.Header.Handle = SmbiosHandle;\r
928 EndStructure.Tailing[0] = 0;\r
929 EndStructure.Tailing[1] = 0;\r
930 EntryPointStructure->NumberOfSmbiosStructures++;\r
931 EntryPointStructure->TableLength = (UINT16) (EntryPointStructure->TableLength + sizeof (EndStructure));\r
932 if (sizeof (EndStructure) > EntryPointStructure->MaxStructureSize) {\r
933 EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);\r
934 }\r
310b04e6 935\r
f93161b4 936 if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > PreAllocatedPages) {\r
0ddd8553 937 //\r
938 // If new SMBIOS talbe size exceeds the original pre-allocated page, \r
939 // it is time to re-allocate memory (below 4GB).\r
940 // \r
941 if (EntryPointStructure->TableAddress != 0) {\r
942 //\r
943 // Free the original pre-allocated page\r
944 // \r
945 FreePages (\r
946 (VOID*)(UINTN)EntryPointStructure->TableAddress,\r
947 PreAllocatedPages\r
948 );\r
949 EntryPointStructure->TableAddress = 0;\r
950 }\r
951 \r
952 PhysicalAddress = 0xffffffff;\r
953 Status = gBS->AllocatePages (\r
954 AllocateMaxAddress,\r
955 EfiReservedMemoryType,\r
956 EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r
957 &PhysicalAddress\r
958 );\r
959 if (EFI_ERROR (Status)) {\r
960 return EFI_OUT_OF_RESOURCES;\r
961 }\r
962 EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
963 }\r
310b04e6 964 \r
965 //\r
966 // Assemble the tables\r
967 //\r
0ddd8553 968 BufferPointer = (UINT8 *) (UINTN) EntryPointStructure->TableAddress;\r
969 CurrentSmbiosEntry = NULL;\r
310b04e6 970 do {\r
0ddd8553 971 Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
972\r
310b04e6 973 if (Status == EFI_SUCCESS) {\r
afe3969c 974 GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
310b04e6 975 CopyMem (BufferPointer, SmbiosRecord, RecordSize);\r
976 BufferPointer = BufferPointer + RecordSize;\r
977 }\r
978 } while (!EFI_ERROR(Status));\r
979 \r
980 //\r
981 // Assemble End-Of-Table structure\r
982 //\r
983 CopyMem (BufferPointer, &EndStructure, sizeof (EndStructure));\r
984\r
985 //\r
986 // Fixup checksums in the Entry Point Structure\r
987 //\r
afe3969c
SZ
988 EntryPointStructure->IntermediateChecksum =\r
989 CalculateCheckSum8 ((UINT8 *) EntryPointStructure + 0x10, EntryPointStructure->EntryPointLength - 0x10);\r
990 EntryPointStructure->EntryPointStructureChecksum =\r
991 CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength);\r
310b04e6 992\r
993 //\r
994 // Returns the pointer\r
995 //\r
996 *TableEntryPointStructure = EntryPointStructure;\r
997\r
998 return EFI_SUCCESS;\r
999}\r
1000\r
310b04e6 1001/**\r
0ddd8553 1002 Create SMBIOS Table and install it to the System Table.\r
310b04e6 1003**/\r
1004VOID\r
1005EFIAPI\r
1006SmbiosTableConstruction (\r
0ddd8553 1007 VOID\r
310b04e6 1008 )\r
1009{\r
1010 UINT8 *Eps;\r
1011 EFI_STATUS Status;\r
1012\r
1013 Status = SmbiosCreateTable ((VOID **) &Eps);\r
1014 if (!EFI_ERROR (Status)) {\r
1015 gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, Eps);\r
1016 }\r
1017}\r
1018\r
310b04e6 1019/**\r
1020\r
0ddd8553 1021 Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table. \r
310b04e6 1022\r
1023 @param ImageHandle Module's image handle\r
1024 @param SystemTable Pointer of EFI_SYSTEM_TABLE\r
1025\r
1026 @retval EFI_SUCCESS Smbios protocol installed\r
1027 @retval Other No protocol installed, unload driver.\r
1028\r
1029**/\r
1030EFI_STATUS\r
1031EFIAPI\r
1032SmbiosDriverEntryPoint (\r
1033 IN EFI_HANDLE ImageHandle,\r
1034 IN EFI_SYSTEM_TABLE *SystemTable\r
1035 )\r
1036{\r
1037 EFI_STATUS Status;\r
0ddd8553 1038 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
310b04e6 1039\r
1040 mPrivateData.Signature = SMBIOS_INSTANCE_SIGNATURE;\r
1041 mPrivateData.Smbios.Add = SmbiosAdd;\r
1042 mPrivateData.Smbios.UpdateString = SmbiosUpdateString;\r
1043 mPrivateData.Smbios.Remove = SmbiosRemove;\r
1044 mPrivateData.Smbios.GetNext = SmbiosGetNext;\r
9f7d5b46 1045 mPrivateData.Smbios.MajorVersion = (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) >> 8);\r
1046 mPrivateData.Smbios.MinorVersion = (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) & 0x00ff);\r
310b04e6 1047\r
1048 InitializeListHead (&mPrivateData.DataListHead);\r
1049 InitializeListHead (&mPrivateData.AllocatedHandleListHead);\r
1050 EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);\r
0ddd8553 1051\r
1052 //\r
1053 // Initialize the EntryPointStructure with initial values.\r
1054 // Allocate memory (below 4GB).\r
1055 //\r
1056 PhysicalAddress = 0xffffffff;\r
1057 Status = gBS->AllocatePages (\r
1058 AllocateMaxAddress,\r
1059 EfiReservedMemoryType,\r
1060 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
1061 &PhysicalAddress\r
1062 );\r
1063 if (EFI_ERROR (Status)) {\r
1064 return EFI_OUT_OF_RESOURCES;\r
1065 }\r
1066\r
1067 EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) (UINTN) PhysicalAddress;\r
310b04e6 1068 \r
0ddd8553 1069 CopyMem (\r
1070 EntryPointStructure,\r
1071 &EntryPointStructureData,\r
1072 sizeof (SMBIOS_TABLE_ENTRY_POINT)\r
1073 );\r
1074\r
1075 //\r
1076 // Pre-allocate 1 page for SMBIOS table below 4GB.\r
1077 // SMBIOS table will be updated when new SMBIOS type is added or \r
1078 // existing SMBIOS type is updated. If the total size of SMBIOS table exceeds 1 page,\r
1079 // we will re-allocate new memory when creating whole SMBIOS table.\r
1080 //\r
1081 PhysicalAddress = 0xffffffff;\r
1082 Status = gBS->AllocatePages (\r
1083 AllocateMaxAddress,\r
1084 EfiReservedMemoryType,\r
1085 1,\r
1086 &PhysicalAddress\r
1087 );\r
1088 if (EFI_ERROR (Status)) {\r
1089 FreePages ((VOID*) EntryPointStructure, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)));\r
1090 EntryPointStructure = NULL;\r
1091 return EFI_OUT_OF_RESOURCES;\r
1092 }\r
1093\r
1094 EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
1095 EntryPointStructure->TableLength = EFI_PAGES_TO_SIZE (1);\r
1096\r
310b04e6 1097 //\r
1098 // Make a new handle and install the protocol\r
1099 //\r
1100 mPrivateData.Handle = NULL;\r
1101 Status = gBS->InstallProtocolInterface (\r
1102 &mPrivateData.Handle,\r
1103 &gEfiSmbiosProtocolGuid,\r
1104 EFI_NATIVE_INTERFACE,\r
1105 &mPrivateData.Smbios\r
1106 );\r
1107\r
310b04e6 1108 return Status;\r
1109}\r