Add Lock for cirtical section in PCD database processing routines as PCD database...
[mirror_edk2.git] / EdkModulePkg / Universal / PCD / Dxe / Pcd.c
CommitLineData
878ddf1f 1/** @file\r
2PCD DXE driver\r
3\r
4Copyright (c) 2006, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13\r
14Module Name: Pcd.c\r
15\r
16**/\r
17\r
878ddf1f 18#include "Service.h"\r
19\r
a696a78c 20EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(EFI_TPL_CALLBACK);\r
878ddf1f 21\r
22PCD_PROTOCOL mPcdInstance = {\r
23 DxePcdSetSku,\r
24\r
25 DxePcdGet8,\r
26 DxePcdGet16,\r
27 DxePcdGet32,\r
28 DxePcdGet64,\r
29 DxePcdGetPtr,\r
30 DxePcdGetBool,\r
31 DxePcdGetSize,\r
32\r
33 DxePcdGet8Ex,\r
34 DxePcdGet16Ex,\r
35 DxePcdGet32Ex,\r
36 DxePcdGet64Ex,\r
37 DxePcdGetPtrEx,\r
38 DxePcdGetBoolEx,\r
39 DxePcdGetSizeEx,\r
40\r
41 DxePcdSet8,\r
42 DxePcdSet16,\r
43 DxePcdSet32,\r
44 DxePcdSet64,\r
45 DxePcdSetPtr,\r
46 DxePcdSetBool,\r
47\r
48 DxePcdSet8Ex,\r
49 DxePcdSet16Ex,\r
50 DxePcdSet32Ex,\r
51 DxePcdSet64Ex,\r
52 DxePcdSetPtrEx,\r
53 DxePcdSetBoolEx,\r
54\r
4c114006 55 DxeRegisterCallBackOnSet,\r
56 DxeUnRegisterCallBackOnSet,\r
c24ba2f6 57 DxePcdGetNextToken,\r
58 DxePcdGetNextTokenSpace\r
878ddf1f 59};\r
60\r
61\r
62//\r
63// Static global to reduce the code size\r
64//\r
3b06f97c 65static EFI_HANDLE mNewHandle = NULL;\r
878ddf1f 66\r
67EFI_STATUS\r
68EFIAPI\r
69PcdDxeInit (\r
70 IN EFI_HANDLE ImageHandle,\r
71 IN EFI_SYSTEM_TABLE *SystemTable\r
72 )\r
73{\r
52e1905d 74 EFI_STATUS Status;\r
75\r
76 //\r
77 // Make sure the Pcd Protocol is not already installed in the system\r
78 //\r
4f242357 79\r
52e1905d 80 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);\r
2a505eac 81\r
52e1905d 82 BuildPcdDxeDataBase ();\r
83\r
878ddf1f 84 Status = gBS->InstallProtocolInterface (\r
3b06f97c 85 &mNewHandle,\r
878ddf1f 86 &gPcdProtocolGuid,\r
87 EFI_NATIVE_INTERFACE,\r
88 &mPcdInstance\r
89 );\r
90\r
91 ASSERT_EFI_ERROR (Status);\r
92\r
93 return EFI_SUCCESS;\r
94\r
95}\r
96\r
97\r
00b7af13 98VOID\r
878ddf1f 99EFIAPI\r
100DxePcdSetSku (\r
8a43e8dd 101 IN UINTN SkuId\r
878ddf1f 102 )\r
103{\r
8a43e8dd 104 mPcdDatabase->PeiDb.Init.SystemSkuId = (SKU_ID) SkuId;\r
00b7af13 105 \r
106 return;\r
878ddf1f 107}\r
108\r
109\r
110\r
111UINT8\r
112EFIAPI\r
113DxePcdGet8 (\r
8a43e8dd 114 IN UINTN TokenNumber\r
878ddf1f 115 )\r
116{\r
9d6d8b24 117 return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));\r
878ddf1f 118}\r
119\r
120\r
121\r
122UINT16\r
123EFIAPI\r
124DxePcdGet16 (\r
8a43e8dd 125 IN UINTN TokenNumber\r
878ddf1f 126 )\r
127{\r
9d6d8b24 128 return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));\r
878ddf1f 129}\r
130\r
131\r
132\r
133UINT32\r
134EFIAPI\r
135DxePcdGet32 (\r
8a43e8dd 136 IN UINTN TokenNumber\r
878ddf1f 137 )\r
138{\r
9d6d8b24 139 return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));\r
878ddf1f 140}\r
141\r
142\r
143\r
144UINT64\r
145EFIAPI\r
146DxePcdGet64 (\r
8a43e8dd 147 IN UINTN TokenNumber\r
878ddf1f 148 )\r
149{\r
9d6d8b24 150 return ReadUnaligned64(GetWorker (TokenNumber, sizeof (UINT64)));\r
878ddf1f 151}\r
152\r
153\r
154\r
155VOID *\r
156EFIAPI\r
157DxePcdGetPtr (\r
8a43e8dd 158 IN UINTN TokenNumber\r
878ddf1f 159 )\r
160{\r
9d6d8b24 161 return GetWorker (TokenNumber, 0);\r
878ddf1f 162}\r
163\r
164\r
165\r
166BOOLEAN\r
167EFIAPI\r
168DxePcdGetBool (\r
8a43e8dd 169 IN UINTN TokenNumber\r
878ddf1f 170 )\r
171{\r
9d6d8b24 172 return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));\r
878ddf1f 173}\r
174\r
175\r
176\r
177UINTN\r
178EFIAPI\r
179DxePcdGetSize (\r
8a43e8dd 180 IN UINTN TokenNumber\r
878ddf1f 181 )\r
182{\r
1de04b4f 183 UINTN Size;\r
184 UINT32 *LocalTokenNumberTable;\r
185 BOOLEAN IsPeiDb;\r
186 UINTN MaxSize;\r
187 UINTN TmpTokenNumber;\r
58f1099f 188 //\r
189 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
190 // We have to decrement TokenNumber by 1 to make it usable\r
191 // as the array index.\r
192 //\r
193 TokenNumber--;\r
1de04b4f 194\r
195 //\r
196 // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber\r
197 // \r
198 TmpTokenNumber = TokenNumber;\r
199\r
4f914125 200 // EBC compiler is very choosy. It may report warning about comparison\r
201 // between UINTN and 0 . So we add 1 in each size of the \r
202 // comparison.\r
203 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
204\r
205 // EBC compiler is very choosy. It may report warning about comparison\r
206 // between UINTN and 0 . So we add 1 in each size of the \r
207 // comparison.\r
208 IsPeiDb = (BOOLEAN) (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
58f1099f 209 \r
1de04b4f 210 TokenNumber = IsPeiDb ? TokenNumber : \r
211 (TokenNumber - PEI_LOCAL_TOKEN_NUMBER);\r
52e1905d 212\r
1de04b4f 213 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable \r
214 : mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
52e1905d 215\r
1de04b4f 216 Size = (LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;\r
217\r
218 if (Size == 0) {\r
219 //\r
220 // For pointer type, we need to scan the SIZE_TABLE to get the current size.\r
221 //\r
222 return GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
223 } else {\r
224 return Size;\r
225 }\r
52e1905d 226\r
878ddf1f 227}\r
228\r
229\r
230\r
231UINT8\r
232EFIAPI\r
233DxePcdGet8Ex (\r
52e1905d 234 IN CONST EFI_GUID *Guid,\r
8a43e8dd 235 IN UINTN ExTokenNumber\r
878ddf1f 236 )\r
237{\r
52e1905d 238 return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof(UINT8)));\r
878ddf1f 239}\r
240\r
241\r
242\r
243UINT16\r
244EFIAPI\r
245DxePcdGet16Ex (\r
246 IN CONST EFI_GUID *Guid,\r
8a43e8dd 247 IN UINTN ExTokenNumber\r
878ddf1f 248 )\r
249{\r
9d6d8b24 250 return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT16)));\r
878ddf1f 251}\r
252\r
253\r
254\r
255UINT32\r
256EFIAPI\r
257DxePcdGet32Ex (\r
258 IN CONST EFI_GUID *Guid,\r
8a43e8dd 259 IN UINTN ExTokenNumber\r
878ddf1f 260 )\r
261{\r
9d6d8b24 262 return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT32)));\r
878ddf1f 263}\r
264\r
265\r
266\r
267UINT64\r
268EFIAPI\r
269DxePcdGet64Ex (\r
270 IN CONST EFI_GUID *Guid,\r
8a43e8dd 271 IN UINTN ExTokenNumber\r
878ddf1f 272 )\r
273{\r
9d6d8b24 274 return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT64)));\r
878ddf1f 275}\r
276\r
277\r
278\r
279VOID *\r
280EFIAPI\r
281DxePcdGetPtrEx (\r
282 IN CONST EFI_GUID *Guid,\r
8a43e8dd 283 IN UINTN ExTokenNumber\r
878ddf1f 284 )\r
285{\r
1de04b4f 286 return ExGetWorker (Guid, ExTokenNumber, 0);\r
878ddf1f 287}\r
288\r
289\r
290\r
291BOOLEAN\r
292EFIAPI\r
293DxePcdGetBoolEx (\r
294 IN CONST EFI_GUID *Guid,\r
8a43e8dd 295 IN UINTN ExTokenNumber\r
878ddf1f 296 )\r
297{\r
52e1905d 298 return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof(BOOLEAN)));\r
878ddf1f 299}\r
300\r
301\r
302\r
303UINTN\r
304EFIAPI\r
305DxePcdGetSizeEx (\r
306 IN CONST EFI_GUID *Guid,\r
8a43e8dd 307 IN UINTN ExTokenNumber\r
878ddf1f 308 )\r
309{\r
4f242357 310 return DxePcdGetSize(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber));\r
878ddf1f 311}\r
312\r
313\r
314\r
315EFI_STATUS\r
316EFIAPI\r
317DxePcdSet8 (\r
8a43e8dd 318 IN UINTN TokenNumber,\r
52e1905d 319 IN UINT8 Value\r
878ddf1f 320 )\r
321{\r
1de04b4f 322 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
878ddf1f 323}\r
324\r
325\r
326\r
327EFI_STATUS\r
328EFIAPI\r
329DxePcdSet16 (\r
8a43e8dd 330 IN UINTN TokenNumber,\r
878ddf1f 331 IN UINT16 Value\r
332 )\r
333{\r
1de04b4f 334 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
878ddf1f 335}\r
336\r
337\r
338\r
339EFI_STATUS\r
340EFIAPI\r
341DxePcdSet32 (\r
8a43e8dd 342 IN UINTN TokenNumber,\r
878ddf1f 343 IN UINT32 Value\r
344 )\r
345{\r
1de04b4f 346 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
878ddf1f 347}\r
348\r
349\r
350\r
351EFI_STATUS\r
352EFIAPI\r
353DxePcdSet64 (\r
8a43e8dd 354 IN UINTN TokenNumber,\r
52e1905d 355 IN UINT64 Value\r
878ddf1f 356 )\r
357{\r
1de04b4f 358 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
878ddf1f 359}\r
360\r
361\r
362\r
363EFI_STATUS\r
364EFIAPI\r
365DxePcdSetPtr (\r
1de04b4f 366 IN UINTN TokenNumber,\r
367 IN OUT UINTN *SizeOfBuffer,\r
368 IN VOID *Buffer\r
878ddf1f 369 )\r
370{\r
00b7af13 371 return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);\r
878ddf1f 372}\r
373\r
374\r
375\r
376EFI_STATUS\r
377EFIAPI\r
378DxePcdSetBool (\r
8a43e8dd 379 IN UINTN TokenNumber,\r
52e1905d 380 IN BOOLEAN Value\r
878ddf1f 381 )\r
382{\r
1de04b4f 383 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
878ddf1f 384}\r
385\r
386\r
387\r
388EFI_STATUS\r
389EFIAPI\r
390DxePcdSet8Ex (\r
4c114006 391 IN CONST EFI_GUID *Guid,\r
8a43e8dd 392 IN UINTN ExTokenNumber,\r
52e1905d 393 IN UINT8 Value\r
878ddf1f 394 )\r
395{\r
1de04b4f 396 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
878ddf1f 397}\r
398\r
399\r
400\r
401EFI_STATUS\r
402EFIAPI\r
403DxePcdSet16Ex (\r
4c114006 404 IN CONST EFI_GUID *Guid,\r
8a43e8dd 405 IN UINTN ExTokenNumber,\r
878ddf1f 406 IN UINT16 Value\r
407 )\r
408{\r
1de04b4f 409 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
878ddf1f 410}\r
411\r
412\r
413\r
414EFI_STATUS\r
415EFIAPI\r
416DxePcdSet32Ex (\r
4c114006 417 IN CONST EFI_GUID *Guid,\r
8a43e8dd 418 IN UINTN ExTokenNumber,\r
878ddf1f 419 IN UINT32 Value\r
420 )\r
421{\r
1de04b4f 422 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
878ddf1f 423}\r
424\r
425\r
426\r
427EFI_STATUS\r
428EFIAPI\r
429DxePcdSet64Ex (\r
4c114006 430 IN CONST EFI_GUID *Guid,\r
8a43e8dd 431 IN UINTN ExTokenNumber,\r
878ddf1f 432 IN UINT64 Value\r
433 )\r
434{\r
1de04b4f 435 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
878ddf1f 436}\r
437\r
438\r
439\r
440EFI_STATUS\r
441EFIAPI\r
442DxePcdSetPtrEx (\r
1de04b4f 443 IN CONST EFI_GUID *Guid,\r
444 IN UINTN ExTokenNumber,\r
445 IN OUT UINTN *SizeOfBuffer,\r
446 IN VOID *Buffer\r
878ddf1f 447 )\r
448{\r
1de04b4f 449 return ExSetWorker(ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);\r
878ddf1f 450}\r
451\r
452\r
453\r
454EFI_STATUS\r
455EFIAPI\r
456DxePcdSetBoolEx (\r
4c114006 457 IN CONST EFI_GUID *Guid,\r
8a43e8dd 458 IN UINTN ExTokenNumber,\r
878ddf1f 459 IN BOOLEAN Value\r
460 )\r
461{\r
1de04b4f 462 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
878ddf1f 463}\r
464\r
465\r
466\r
467\r
468EFI_STATUS\r
469EFIAPI\r
4c114006 470DxeRegisterCallBackOnSet (\r
4c114006 471 IN CONST EFI_GUID *Guid, OPTIONAL\r
2a870f53 472 IN UINTN TokenNumber,\r
878ddf1f 473 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
474 )\r
475{\r
a696a78c 476 EFI_STATUS Status;\r
477 \r
4c114006 478 ASSERT (CallBackFunction != NULL);\r
479 \r
a696a78c 480 //\r
481 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
482 //\r
483 EfiAcquireLock (&mPcdDatabaseLock);\r
484\r
485 Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);\r
486\r
487 EfiReleaseLock (&mPcdDatabaseLock);\r
488 \r
489 return Status;\r
878ddf1f 490}\r
491\r
492\r
493\r
494EFI_STATUS\r
495EFIAPI\r
4c114006 496DxeUnRegisterCallBackOnSet (\r
4c114006 497 IN CONST EFI_GUID *Guid, OPTIONAL\r
2a870f53 498 IN UINTN TokenNumber,\r
878ddf1f 499 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
500 )\r
501{\r
a696a78c 502 EFI_STATUS Status;\r
503 \r
4c114006 504 ASSERT (CallBackFunction != NULL);\r
a696a78c 505\r
506 //\r
507 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
508 //\r
509 EfiAcquireLock (&mPcdDatabaseLock);\r
510 \r
511 Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);\r
512\r
513 EfiReleaseLock (&mPcdDatabaseLock);\r
4c114006 514 \r
a696a78c 515 return Status;\r
878ddf1f 516}\r
517\r
518\r
519\r
520EFI_STATUS\r
521EFIAPI\r
522DxePcdGetNextToken (\r
4c114006 523 IN CONST EFI_GUID *Guid, OPTIONAL\r
8a43e8dd 524 IN OUT UINTN *TokenNumber\r
878ddf1f 525 )\r
526{\r
2b21a971 527 EFI_STATUS Status;\r
528\r
4f914125 529 if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {\r
530 return EFI_UNSUPPORTED;\r
531 }\r
532\r
2b21a971 533 Status = EFI_NOT_FOUND;\r
4c114006 534 //\r
535 // Scan the local token space\r
536 //\r
537 if (Guid == NULL) {\r
4f914125 538 // EBC compiler is very choosy. It may report warning about comparison\r
539 // between UINTN and 0 . So we add 1 in each size of the \r
540 // comparison.\r
541 if (((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) && (*TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1)) ||\r
542 ((*TokenNumber + 1 > (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1)))) {\r
2b21a971 543 return EFI_NOT_FOUND;\r
544 }\r
545 \r
dcec7651 546 (*TokenNumber)++;\r
4f914125 547 if ((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) &&\r
548 (*TokenNumber <= PEI_LOCAL_TOKEN_NUMBER)) {\r
c24ba2f6 549 //\r
550 // The first Non-Ex type Token Number for DXE PCD \r
551 // database is PEI_LOCAL_TOKEN_NUMBER\r
552 //\r
553 *TokenNumber = PEI_LOCAL_TOKEN_NUMBER;\r
4f914125 554 } else if (*TokenNumber + 1 > DXE_NEX_TOKEN_NUMBER + PEI_LOCAL_TOKEN_NUMBER + 1) {\r
c24ba2f6 555 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
4c114006 556 }\r
c24ba2f6 557 return EFI_SUCCESS;\r
4c114006 558 }\r
559\r
c24ba2f6 560 if (PEI_EXMAP_TABLE_EMPTY && DXE_EXMAP_TABLE_EMPTY) {\r
561 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
4c114006 562 return EFI_NOT_FOUND;\r
563 }\r
564\r
4c114006 565 if (!PEI_EXMAP_TABLE_EMPTY) {\r
2b21a971 566 Status = ExGetNextTokeNumber (\r
4c114006 567 Guid,\r
2b21a971 568 TokenNumber,\r
4c114006 569 mPcdDatabase->PeiDb.Init.GuidTable,\r
570 sizeof(mPcdDatabase->PeiDb.Init.GuidTable),\r
571 mPcdDatabase->PeiDb.Init.ExMapTable,\r
572 sizeof(mPcdDatabase->PeiDb.Init.ExMapTable)\r
573 );\r
574 }\r
575\r
2b21a971 576 if (Status == EFI_SUCCESS) {\r
577 return Status;\r
578 }\r
579\r
580 if (!DXE_EXMAP_TABLE_EMPTY) {\r
581 Status = ExGetNextTokeNumber (\r
4c114006 582 Guid,\r
2b21a971 583 TokenNumber,\r
c24ba2f6 584 mPcdDatabase->DxeDb.Init.GuidTable,\r
585 sizeof(mPcdDatabase->DxeDb.Init.GuidTable),\r
586 mPcdDatabase->DxeDb.Init.ExMapTable,\r
587 sizeof(mPcdDatabase->DxeDb.Init.ExMapTable)\r
4c114006 588 );\r
589 }\r
590\r
2b21a971 591 return Status;\r
878ddf1f 592}\r
593\r
4276d5da 594\r
595EFI_GUID **\r
596GetDistinctTokenSpace (\r
597 IN OUT UINTN *ExMapTableSize,\r
598 IN DYNAMICEX_MAPPING *ExMapTable,\r
599 IN EFI_GUID *GuidTable\r
600 )\r
601{\r
602 EFI_GUID **DistinctTokenSpace;\r
603 UINTN OldGuidIndex;\r
604 UINTN TsIdx;\r
605 UINTN Idx;\r
606\r
607\r
608 DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));\r
609 ASSERT (DistinctTokenSpace != NULL);\r
610\r
611 TsIdx = 0;\r
612 OldGuidIndex = ExMapTable[0].ExGuidIndex;\r
613 DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];\r
c24ba2f6 614 for (Idx = 1; Idx < *ExMapTableSize; Idx++) {\r
4276d5da 615 if (ExMapTable[Idx].ExGuidIndex != OldGuidIndex) {\r
616 OldGuidIndex = ExMapTable[Idx].ExGuidIndex;\r
617 DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];\r
618 }\r
619 }\r
620\r
c24ba2f6 621 //\r
622 // The total number of Distinct Token Space\r
623 // is TsIdx + 1 because we use TsIdx as a index\r
624 // to the DistinctTokenSpace[]\r
625 //\r
626 *ExMapTableSize = TsIdx + 1;\r
4276d5da 627 return DistinctTokenSpace;\r
628 \r
629}\r
630 \r
c24ba2f6 631//\r
632// Just pre-allocate a memory buffer that is big enough to\r
633// host all distinct TokenSpace guid in both\r
634// PEI ExMap and DXE ExMap.\r
635//\r
4276d5da 636STATIC EFI_GUID *TmpTokenSpaceBuffer[PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE] = { 0 };\r
637\r
638EFI_STATUS\r
639EFIAPI\r
640DxePcdGetNextTokenSpace (\r
641 IN OUT CONST EFI_GUID **Guid\r
642 )\r
643{\r
644 UINTN Idx;\r
645 UINTN Idx2;\r
646 UINTN Idx3;\r
647 UINTN PeiTokenSpaceTableSize;\r
648 UINTN DxeTokenSpaceTableSize;\r
649 EFI_GUID **PeiTokenSpaceTable;\r
650 EFI_GUID **DxeTokenSpaceTable;\r
651 BOOLEAN Match;\r
652\r
4f914125 653 if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {\r
654 return EFI_UNSUPPORTED;\r
655 }\r
656\r
4276d5da 657 ASSERT (Guid != NULL);\r
658 \r
659 if (PEI_EXMAP_TABLE_EMPTY && DXE_EXMAP_TABLE_EMPTY) {\r
660 if (*Guid != NULL) {\r
661 return EFI_NOT_FOUND;\r
662 } else {\r
663 return EFI_SUCCESS;\r
664 }\r
665 }\r
666 \r
667 \r
c24ba2f6 668 if (TmpTokenSpaceBuffer[0] == NULL) {\r
4276d5da 669 PeiTokenSpaceTableSize = 0;\r
670\r
671 if (!PEI_EXMAP_TABLE_EMPTY) {\r
672 PeiTokenSpaceTableSize = PEI_EXMAPPING_TABLE_SIZE;\r
673 PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize,\r
674 mPcdDatabase->PeiDb.Init.ExMapTable,\r
675 mPcdDatabase->PeiDb.Init.GuidTable\r
676 );\r
677 CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize);\r
678 }\r
679\r
680 if (!DXE_EXMAP_TABLE_EMPTY) {\r
681 DxeTokenSpaceTableSize = DXE_EXMAPPING_TABLE_SIZE;\r
682 DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize,\r
683 mPcdDatabase->DxeDb.Init.ExMapTable,\r
684 mPcdDatabase->DxeDb.Init.GuidTable\r
685 );\r
686\r
687 //\r
688 // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable\r
689 //\r
690 for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {\r
691 Match = FALSE;\r
692 for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {\r
693 if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {\r
694 Match = TRUE;\r
695 break;\r
696 }\r
697 }\r
698 if (!Match) {\r
699 TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];\r
700 }\r
701 }\r
702 }\r
703 }\r
704\r
705 if (*Guid == NULL) {\r
706 *Guid = TmpTokenSpaceBuffer[0];\r
707 return EFI_SUCCESS;\r
708 }\r
709 \r
710 for (Idx = 0; Idx < (PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE); Idx++) {\r
711 if(CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {\r
712 Idx++;\r
713 *Guid = TmpTokenSpaceBuffer[Idx];\r
714 return EFI_SUCCESS;\r
715 }\r
716 }\r
717\r
718 return EFI_NOT_FOUND;\r
719\r
720}\r
721\r
722\r