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