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