]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/PCD/Dxe/Pcd.c
MdeModulePkg: Update PCD driver to support the optimized PcdDataBase
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Pcd.c
... / ...
CommitLineData
1/** @file\r
2 PCD DXE driver manage all PCD entry initialized in PEI phase and DXE phase, and\r
3 produce the implementation of native PCD protocol and EFI_PCD_PROTOCOL defined in\r
4 PI 1.4a Vol3.\r
5\r
6Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "Service.h"\r
18\r
19///\r
20/// PCD database lock.\r
21///\r
22EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_NOTIFY);\r
23\r
24///\r
25/// PCD_PROTOCOL the EDKII native implementation which support dynamic \r
26/// type and dynamicEx type PCDs.\r
27///\r
28PCD_PROTOCOL mPcdInstance = {\r
29 DxePcdSetSku,\r
30\r
31 DxePcdGet8,\r
32 DxePcdGet16,\r
33 DxePcdGet32,\r
34 DxePcdGet64,\r
35 DxePcdGetPtr,\r
36 DxePcdGetBool,\r
37 DxePcdGetSize,\r
38\r
39 DxePcdGet8Ex,\r
40 DxePcdGet16Ex,\r
41 DxePcdGet32Ex,\r
42 DxePcdGet64Ex,\r
43 DxePcdGetPtrEx,\r
44 DxePcdGetBoolEx,\r
45 DxePcdGetSizeEx,\r
46\r
47 DxePcdSet8,\r
48 DxePcdSet16,\r
49 DxePcdSet32,\r
50 DxePcdSet64,\r
51 DxePcdSetPtr,\r
52 DxePcdSetBool,\r
53\r
54 DxePcdSet8Ex,\r
55 DxePcdSet16Ex,\r
56 DxePcdSet32Ex,\r
57 DxePcdSet64Ex,\r
58 DxePcdSetPtrEx,\r
59 DxePcdSetBoolEx,\r
60\r
61 DxeRegisterCallBackOnSet,\r
62 DxeUnRegisterCallBackOnSet,\r
63 DxePcdGetNextToken,\r
64 DxePcdGetNextTokenSpace\r
65};\r
66\r
67///\r
68/// EFI_PCD_PROTOCOL is defined in PI 1.2 Vol 3 which only support dynamicEx type\r
69/// PCD.\r
70///\r
71EFI_PCD_PROTOCOL mEfiPcdInstance = {\r
72 DxePcdSetSku,\r
73 DxePcdGet8Ex,\r
74 DxePcdGet16Ex,\r
75 DxePcdGet32Ex,\r
76 DxePcdGet64Ex,\r
77 DxePcdGetPtrEx,\r
78 DxePcdGetBoolEx,\r
79 DxePcdGetSizeEx,\r
80 DxePcdSet8Ex,\r
81 DxePcdSet16Ex,\r
82 DxePcdSet32Ex,\r
83 DxePcdSet64Ex,\r
84 DxePcdSetPtrEx,\r
85 DxePcdSetBoolEx,\r
86 (EFI_PCD_PROTOCOL_CALLBACK_ON_SET) DxeRegisterCallBackOnSet,\r
87 (EFI_PCD_PROTOCOL_CANCEL_CALLBACK) DxeUnRegisterCallBackOnSet,\r
88 DxePcdGetNextToken,\r
89 DxePcdGetNextTokenSpace\r
90};\r
91\r
92///\r
93/// Instance of GET_PCD_INFO_PROTOCOL protocol is EDKII native implementation.\r
94/// This protocol instance support dynamic and dynamicEx type PCDs.\r
95///\r
96GET_PCD_INFO_PROTOCOL mGetPcdInfoInstance = {\r
97 DxeGetPcdInfoGetInfo,\r
98 DxeGetPcdInfoGetInfoEx,\r
99 DxeGetPcdInfoGetSku\r
100};\r
101\r
102///\r
103/// Instance of EFI_GET_PCD_INFO_PROTOCOL which is defined in PI 1.2.1 Vol 3.\r
104/// This PPI instance only support dyanmicEx type PCD.\r
105///\r
106EFI_GET_PCD_INFO_PROTOCOL mEfiGetPcdInfoInstance = {\r
107 DxeGetPcdInfoGetInfoEx,\r
108 DxeGetPcdInfoGetSku\r
109};\r
110\r
111EFI_HANDLE mPcdHandle = NULL;\r
112\r
113/**\r
114 Main entry for PCD DXE driver.\r
115 \r
116 This routine initialize the PCD database and install PCD_PROTOCOL.\r
117 \r
118 @param ImageHandle Image handle for PCD DXE driver.\r
119 @param SystemTable Pointer to SystemTable.\r
120\r
121 @return Status of gBS->InstallProtocolInterface()\r
122\r
123**/\r
124EFI_STATUS\r
125EFIAPI\r
126PcdDxeInit (\r
127 IN EFI_HANDLE ImageHandle,\r
128 IN EFI_SYSTEM_TABLE *SystemTable\r
129 )\r
130{\r
131 EFI_STATUS Status;\r
132 VOID *Registration;\r
133\r
134 //\r
135 // Make sure the Pcd Protocol is not already installed in the system\r
136 //\r
137\r
138 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);\r
139\r
140 BuildPcdDxeDataBase ();\r
141\r
142 //\r
143 // Install PCD_PROTOCOL to handle dynamic type PCD\r
144 // Install EFI_PCD_PROTOCOL to handle dynamicEx type PCD\r
145 //\r
146 Status = gBS->InstallMultipleProtocolInterfaces (\r
147 &mPcdHandle,\r
148 &gPcdProtocolGuid, &mPcdInstance,\r
149 &gEfiPcdProtocolGuid, &mEfiPcdInstance,\r
150 NULL\r
151 );\r
152 ASSERT_EFI_ERROR (Status);\r
153\r
154 //\r
155 // Install GET_PCD_INFO_PROTOCOL to handle dynamic type PCD\r
156 // Install EFI_GET_PCD_INFO_PROTOCOL to handle dynamicEx type PCD\r
157 //\r
158 Status = gBS->InstallMultipleProtocolInterfaces (\r
159 &mPcdHandle,\r
160 &gGetPcdInfoProtocolGuid, &mGetPcdInfoInstance,\r
161 &gEfiGetPcdInfoProtocolGuid, &mEfiGetPcdInfoInstance,\r
162 NULL\r
163 );\r
164 ASSERT_EFI_ERROR (Status);\r
165\r
166 //\r
167 // Register callback function upon VariableLockProtocol\r
168 // to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.\r
169 //\r
170 EfiCreateProtocolNotifyEvent (\r
171 &gEdkiiVariableLockProtocolGuid,\r
172 TPL_CALLBACK,\r
173 VariableLockCallBack,\r
174 NULL,\r
175 &Registration\r
176 );\r
177\r
178 return Status;\r
179}\r
180\r
181/**\r
182 Retrieve additional information associated with a PCD token in the default token space.\r
183\r
184 This includes information such as the type of value the TokenNumber is associated with as well as possible\r
185 human readable name that is associated with the token.\r
186\r
187 @param[in] TokenNumber The PCD token number.\r
188 @param[out] PcdInfo The returned information associated with the requested TokenNumber.\r
189 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.\r
190\r
191 @retval EFI_SUCCESS The PCD information was returned successfully.\r
192 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
193**/\r
194EFI_STATUS\r
195EFIAPI\r
196DxeGetPcdInfoGetInfo (\r
197 IN UINTN TokenNumber,\r
198 OUT EFI_PCD_INFO *PcdInfo\r
199 )\r
200{\r
201 return DxeGetPcdInfo (NULL, TokenNumber, PcdInfo);\r
202}\r
203\r
204/**\r
205 Retrieve additional information associated with a PCD token.\r
206\r
207 This includes information such as the type of value the TokenNumber is associated with as well as possible\r
208 human readable name that is associated with the token.\r
209\r
210 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
211 @param[in] TokenNumber The PCD token number.\r
212 @param[out] PcdInfo The returned information associated with the requested TokenNumber.\r
213 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.\r
214\r
215 @retval EFI_SUCCESS The PCD information was returned successfully.\r
216 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
217**/\r
218EFI_STATUS\r
219EFIAPI\r
220DxeGetPcdInfoGetInfoEx (\r
221 IN CONST EFI_GUID *Guid,\r
222 IN UINTN TokenNumber,\r
223 OUT EFI_PCD_INFO *PcdInfo\r
224 )\r
225{\r
226 return DxeGetPcdInfo (Guid, TokenNumber, PcdInfo);\r
227}\r
228\r
229/**\r
230 Retrieve the currently set SKU Id.\r
231\r
232 @return The currently set SKU Id. If the platform has not set at a SKU Id, then the\r
233 default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU\r
234 Id is returned.\r
235**/\r
236UINTN\r
237EFIAPI\r
238DxeGetPcdInfoGetSku (\r
239 VOID\r
240 )\r
241{\r
242 return (UINTN) mPcdDatabase.DxeDb->SystemSkuId;\r
243}\r
244\r
245/**\r
246 Sets the SKU value for subsequent calls to set or get PCD token values.\r
247\r
248 SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values. \r
249 SetSku() is normally called only once by the system.\r
250\r
251 For each item (token), the database can hold a single value that applies to all SKUs, \r
252 or multiple values, where each value is associated with a specific SKU Id. Items with multiple, \r
253 SKU-specific values are called SKU enabled. \r
254 \r
255 The SKU Id of zero is reserved as a default.\r
256 For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the \r
257 single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the \r
258 last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token, \r
259 the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been \r
260 set for that Id, the results are unpredictable.\r
261\r
262 @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and \r
263 set values associated with a PCD token.\r
264\r
265**/\r
266VOID\r
267EFIAPI\r
268DxePcdSetSku (\r
269 IN UINTN SkuId\r
270 )\r
271{\r
272 SKU_ID *SkuIdTable;\r
273 UINTN Index;\r
274 EFI_STATUS Status;\r
275\r
276 if (SkuId == mPcdDatabase.DxeDb->SystemSkuId) {\r
277 //\r
278 // The input SKU Id is equal to current SKU Id, return directly.\r
279 //\r
280 return;\r
281 }\r
282\r
283 if (mPcdDatabase.DxeDb->SystemSkuId != (SKU_ID) 0) {\r
284 DEBUG ((DEBUG_ERROR, "PcdDxe - The SKU Id could be changed only once."));\r
285 DEBUG ((\r
286 DEBUG_ERROR,\r
287 "PcdDxe - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",\r
288 mPcdDatabase.DxeDb->SystemSkuId,\r
289 (SKU_ID) SkuId\r
290 ));\r
291 ASSERT (FALSE);\r
292 return;\r
293 }\r
294\r
295 SkuIdTable = (SKU_ID *) ((UINT8 *) mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SkuIdTableOffset);\r
296 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
297 if (SkuId == SkuIdTable[Index + 1]) {\r
298 Status = UpdatePcdDatabase (SkuId, TRUE);\r
299 if (!EFI_ERROR (Status)) {\r
300 mPcdDatabase.DxeDb->SystemSkuId = (SKU_ID) SkuId;\r
301 DEBUG ((DEBUG_INFO, "PcdDxe - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId));\r
302 return;\r
303 }\r
304 }\r
305 }\r
306\r
307 //\r
308 // Invalid input SkuId, the default SKU Id will be still used for the system.\r
309 //\r
310 DEBUG ((DEBUG_INFO, "PcdDxe - Invalid input SkuId, the default SKU Id will be still used.\n"));\r
311 return;\r
312}\r
313\r
314/**\r
315 Retrieves an 8-bit value for a given PCD token.\r
316\r
317 Retrieves the current byte-sized value for a PCD token number. \r
318 If the TokenNumber is invalid, the results are unpredictable.\r
319 \r
320 @param[in] TokenNumber The PCD token number. \r
321\r
322 @return The UINT8 value.\r
323 \r
324**/\r
325UINT8\r
326EFIAPI\r
327DxePcdGet8 (\r
328 IN UINTN TokenNumber\r
329 )\r
330{\r
331 return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));\r
332}\r
333\r
334/**\r
335 Retrieves an 16-bit value for a given PCD token.\r
336\r
337 Retrieves the current 16-bits value for a PCD token number. \r
338 If the TokenNumber is invalid, the results are unpredictable.\r
339 \r
340 @param[in] TokenNumber The PCD token number. \r
341\r
342 @return The UINT16 value.\r
343 \r
344**/\r
345UINT16\r
346EFIAPI\r
347DxePcdGet16 (\r
348 IN UINTN TokenNumber\r
349 )\r
350{\r
351 return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));\r
352}\r
353\r
354/**\r
355 Retrieves an 32-bit value for a given PCD token.\r
356\r
357 Retrieves the current 32-bits value for a PCD token number. \r
358 If the TokenNumber is invalid, the results are unpredictable.\r
359 \r
360 @param[in] TokenNumber The PCD token number. \r
361\r
362 @return The UINT32 value.\r
363 \r
364**/\r
365UINT32\r
366EFIAPI\r
367DxePcdGet32 (\r
368 IN UINTN TokenNumber\r
369 )\r
370{\r
371 return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));\r
372}\r
373\r
374/**\r
375 Retrieves an 64-bit value for a given PCD token.\r
376\r
377 Retrieves the current 64-bits value for a PCD token number. \r
378 If the TokenNumber is invalid, the results are unpredictable.\r
379 \r
380 @param[in] TokenNumber The PCD token number. \r
381\r
382 @return The UINT64 value.\r
383 \r
384**/\r
385UINT64\r
386EFIAPI\r
387DxePcdGet64 (\r
388 IN UINTN TokenNumber\r
389 )\r
390{\r
391 return ReadUnaligned64(GetWorker (TokenNumber, sizeof (UINT64)));\r
392}\r
393\r
394/**\r
395 Retrieves a pointer to a value for a given PCD token.\r
396\r
397 Retrieves the current pointer to the buffer for a PCD token number. \r
398 Do not make any assumptions about the alignment of the pointer that \r
399 is returned by this function call. If the TokenNumber is invalid, \r
400 the results are unpredictable.\r
401\r
402 @param[in] TokenNumber The PCD token number. \r
403\r
404 @return The pointer to the buffer to be retrived.\r
405 \r
406**/\r
407VOID *\r
408EFIAPI\r
409DxePcdGetPtr (\r
410 IN UINTN TokenNumber\r
411 )\r
412{\r
413 return GetWorker (TokenNumber, 0);\r
414}\r
415\r
416/**\r
417 Retrieves a Boolean value for a given PCD token.\r
418\r
419 Retrieves the current boolean value for a PCD token number. \r
420 Do not make any assumptions about the alignment of the pointer that \r
421 is returned by this function call. If the TokenNumber is invalid, \r
422 the results are unpredictable.\r
423\r
424 @param[in] TokenNumber The PCD token number. \r
425\r
426 @return The Boolean value.\r
427 \r
428**/\r
429BOOLEAN\r
430EFIAPI\r
431DxePcdGetBool (\r
432 IN UINTN TokenNumber\r
433 )\r
434{\r
435 return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));\r
436}\r
437\r
438/**\r
439 Retrieves the size of the value for a given PCD token.\r
440\r
441 Retrieves the current size of a particular PCD token. \r
442 If the TokenNumber is invalid, the results are unpredictable.\r
443\r
444 @param[in] TokenNumber The PCD token number. \r
445\r
446 @return The size of the value for the PCD token.\r
447 \r
448**/\r
449UINTN\r
450EFIAPI\r
451DxePcdGetSize (\r
452 IN UINTN TokenNumber\r
453 )\r
454{\r
455 UINTN Size;\r
456 UINT32 *LocalTokenNumberTable;\r
457 BOOLEAN IsPeiDb;\r
458 UINTN MaxSize;\r
459 UINTN TmpTokenNumber;\r
460 //\r
461 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
462 // We have to decrement TokenNumber by 1 to make it usable\r
463 // as the array index.\r
464 //\r
465 TokenNumber--;\r
466\r
467 //\r
468 // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber\r
469 // \r
470 TmpTokenNumber = TokenNumber;\r
471\r
472 // EBC compiler is very choosy. It may report warning about comparison\r
473 // between UINTN and 0 . So we add 1 in each size of the \r
474 // comparison.\r
475 ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);\r
476\r
477 // EBC compiler is very choosy. It may report warning about comparison\r
478 // between UINTN and 0 . So we add 1 in each size of the \r
479 // comparison.\r
480 IsPeiDb = (BOOLEAN) (TokenNumber + 1 < mPeiLocalTokenCount + 1);\r
481 \r
482 TokenNumber = IsPeiDb ? TokenNumber : \r
483 (TokenNumber - mPeiLocalTokenCount);\r
484\r
485 LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) \r
486 : (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
487\r
488 Size = (LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;\r
489\r
490 if (Size == 0) {\r
491 //\r
492 // For pointer type, we need to scan the SIZE_TABLE to get the current size.\r
493 //\r
494 return GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
495 } else {\r
496 return Size;\r
497 }\r
498\r
499}\r
500\r
501/**\r
502 Retrieves an 8-bit value for a given PCD token.\r
503\r
504 Retrieves the 8-bit value of a particular PCD token. \r
505 If the TokenNumber is invalid or the token space\r
506 specified by Guid does not exist, the results are \r
507 unpredictable.\r
508\r
509 @param[in] Guid The token space for the token number.\r
510 @param[in] ExTokenNumber The PCD token number. \r
511\r
512 @return The size 8-bit value for the PCD token.\r
513 \r
514**/\r
515UINT8\r
516EFIAPI\r
517DxePcdGet8Ex (\r
518 IN CONST EFI_GUID *Guid,\r
519 IN UINTN ExTokenNumber\r
520 )\r
521{\r
522 return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof(UINT8)));\r
523}\r
524\r
525/**\r
526 Retrieves an 16-bit value for a given PCD token.\r
527\r
528 Retrieves the 16-bit value of a particular PCD token. \r
529 If the TokenNumber is invalid or the token space\r
530 specified by Guid does not exist, the results are \r
531 unpredictable.\r
532\r
533 @param[in] Guid The token space for the token number.\r
534 @param[in] ExTokenNumber The PCD token number. \r
535\r
536 @return The size 16-bit value for the PCD token.\r
537 \r
538**/\r
539UINT16\r
540EFIAPI\r
541DxePcdGet16Ex (\r
542 IN CONST EFI_GUID *Guid,\r
543 IN UINTN ExTokenNumber\r
544 )\r
545{\r
546 return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT16)));\r
547}\r
548\r
549/**\r
550 Retrieves an 32-bit value for a given PCD token.\r
551\r
552 Retrieves the 32-bit value of a particular PCD token. \r
553 If the TokenNumber is invalid or the token space\r
554 specified by Guid does not exist, the results are \r
555 unpredictable.\r
556\r
557 @param[in] Guid The token space for the token number.\r
558 @param[in] ExTokenNumber The PCD token number. \r
559\r
560 @return The size 32-bit value for the PCD token.\r
561 \r
562**/\r
563UINT32\r
564EFIAPI\r
565DxePcdGet32Ex (\r
566 IN CONST EFI_GUID *Guid,\r
567 IN UINTN ExTokenNumber\r
568 )\r
569{\r
570 return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT32)));\r
571}\r
572\r
573/**\r
574 Retrieves an 64-bit value for a given PCD token.\r
575\r
576 Retrieves the 64-bit value of a particular PCD token. \r
577 If the TokenNumber is invalid or the token space\r
578 specified by Guid does not exist, the results are \r
579 unpredictable.\r
580\r
581 @param[in] Guid The token space for the token number.\r
582 @param[in] ExTokenNumber The PCD token number. \r
583\r
584 @return The size 64-bit value for the PCD token.\r
585 \r
586**/\r
587UINT64\r
588EFIAPI\r
589DxePcdGet64Ex (\r
590 IN CONST EFI_GUID *Guid,\r
591 IN UINTN ExTokenNumber\r
592 )\r
593{\r
594 return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT64)));\r
595}\r
596\r
597/**\r
598 Retrieves a pointer to a value for a given PCD token.\r
599\r
600 Retrieves the current pointer to the buffer for a PCD token number. \r
601 Do not make any assumptions about the alignment of the pointer that \r
602 is returned by this function call. If the TokenNumber is invalid, \r
603 the results are unpredictable.\r
604\r
605 @param[in] Guid The token space for the token number.\r
606 @param[in] ExTokenNumber The PCD token number. \r
607\r
608 @return The pointer to the buffer to be retrived.\r
609 \r
610**/\r
611VOID *\r
612EFIAPI\r
613DxePcdGetPtrEx (\r
614 IN CONST EFI_GUID *Guid,\r
615 IN UINTN ExTokenNumber\r
616 )\r
617{\r
618 return ExGetWorker (Guid, ExTokenNumber, 0);\r
619}\r
620\r
621/**\r
622 Retrieves an Boolean value for a given PCD token.\r
623\r
624 Retrieves the Boolean value of a particular PCD token. \r
625 If the TokenNumber is invalid or the token space\r
626 specified by Guid does not exist, the results are \r
627 unpredictable.\r
628\r
629 @param[in] Guid The token space for the token number.\r
630 @param[in] ExTokenNumber The PCD token number. \r
631\r
632 @return The size Boolean value for the PCD token.\r
633 \r
634**/\r
635BOOLEAN\r
636EFIAPI\r
637DxePcdGetBoolEx (\r
638 IN CONST EFI_GUID *Guid,\r
639 IN UINTN ExTokenNumber\r
640 )\r
641{\r
642 return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof(BOOLEAN)));\r
643}\r
644\r
645/**\r
646 Retrieves the size of the value for a given PCD token.\r
647\r
648 Retrieves the current size of a particular PCD token. \r
649 If the TokenNumber is invalid, the results are unpredictable.\r
650\r
651 @param[in] Guid The token space for the token number.\r
652 @param[in] ExTokenNumber The PCD token number. \r
653\r
654 @return The size of the value for the PCD token.\r
655 \r
656**/\r
657UINTN\r
658EFIAPI\r
659DxePcdGetSizeEx (\r
660 IN CONST EFI_GUID *Guid,\r
661 IN UINTN ExTokenNumber\r
662 )\r
663{\r
664 return DxePcdGetSize(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber));\r
665}\r
666\r
667/**\r
668 Sets an 8-bit value for a given PCD token.\r
669\r
670 When the PCD service sets a value, it will check to ensure that the \r
671 size of the value being set is compatible with the Token's existing definition. \r
672 If it is not, an error will be returned.\r
673\r
674 @param[in] TokenNumber The PCD token number. \r
675 @param[in] Value The value to set for the PCD token.\r
676\r
677 @retval EFI_SUCCESS Procedure returned successfully.\r
678 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
679 being set was incompatible with a call to this function. \r
680 Use GetSize() to retrieve the size of the target data.\r
681 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
682 \r
683**/\r
684EFI_STATUS\r
685EFIAPI\r
686DxePcdSet8 (\r
687 IN UINTN TokenNumber,\r
688 IN UINT8 Value\r
689 )\r
690{\r
691 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
692}\r
693\r
694/**\r
695 Sets an 16-bit value for a given PCD token.\r
696\r
697 When the PCD service sets a value, it will check to ensure that the \r
698 size of the value being set is compatible with the Token's existing definition. \r
699 If it is not, an error will be returned.\r
700\r
701 @param[in] TokenNumber The PCD token number. \r
702 @param[in] Value The value to set for the PCD token.\r
703\r
704 @retval EFI_SUCCESS Procedure returned successfully.\r
705 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
706 being set was incompatible with a call to this function. \r
707 Use GetSize() to retrieve the size of the target data.\r
708 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
709 \r
710**/\r
711EFI_STATUS\r
712EFIAPI\r
713DxePcdSet16 (\r
714 IN UINTN TokenNumber,\r
715 IN UINT16 Value\r
716 )\r
717{\r
718 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
719}\r
720\r
721/**\r
722 Sets an 32-bit value for a given PCD token.\r
723\r
724 When the PCD service sets a value, it will check to ensure that the \r
725 size of the value being set is compatible with the Token's existing definition. \r
726 If it is not, an error will be returned.\r
727\r
728 @param[in] TokenNumber The PCD token number. \r
729 @param[in] Value The value to set for the PCD token.\r
730\r
731 @retval EFI_SUCCESS Procedure returned successfully.\r
732 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
733 being set was incompatible with a call to this function. \r
734 Use GetSize() to retrieve the size of the target data.\r
735 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
736 \r
737**/\r
738EFI_STATUS\r
739EFIAPI\r
740DxePcdSet32 (\r
741 IN UINTN TokenNumber,\r
742 IN UINT32 Value\r
743 )\r
744{\r
745 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
746}\r
747\r
748/**\r
749 Sets an 64-bit value for a given PCD token.\r
750\r
751 When the PCD service sets a value, it will check to ensure that the \r
752 size of the value being set is compatible with the Token's existing definition. \r
753 If it is not, an error will be returned.\r
754\r
755 @param[in] TokenNumber The PCD token number. \r
756 @param[in] Value The value to set for the PCD token.\r
757\r
758 @retval EFI_SUCCESS Procedure returned successfully.\r
759 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
760 being set was incompatible with a call to this function. \r
761 Use GetSize() to retrieve the size of the target data.\r
762 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
763 \r
764**/\r
765EFI_STATUS\r
766EFIAPI\r
767DxePcdSet64 (\r
768 IN UINTN TokenNumber,\r
769 IN UINT64 Value\r
770 )\r
771{\r
772 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
773}\r
774\r
775/**\r
776 Sets a value of a specified size for a given PCD token.\r
777\r
778 When the PCD service sets a value, it will check to ensure that the \r
779 size of the value being set is compatible with the Token's existing definition. \r
780 If it is not, an error will be returned.\r
781\r
782 @param[in] TokenNumber The PCD token number. \r
783 @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token. \r
784 On input, if the SizeOfValue is greater than the maximum size supported \r
785 for this TokenNumber then the output value of SizeOfValue will reflect \r
786 the maximum size supported for this TokenNumber.\r
787 @param[in] Buffer The buffer to set for the PCD token.\r
788\r
789 @retval EFI_SUCCESS Procedure returned successfully.\r
790 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
791 being set was incompatible with a call to this function. \r
792 Use GetSize() to retrieve the size of the target data.\r
793 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
794 \r
795**/\r
796EFI_STATUS\r
797EFIAPI\r
798DxePcdSetPtr (\r
799 IN UINTN TokenNumber,\r
800 IN OUT UINTN *SizeOfBuffer,\r
801 IN VOID *Buffer\r
802 )\r
803{\r
804 return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);\r
805}\r
806\r
807/**\r
808 Sets an Boolean value for a given PCD token.\r
809\r
810 When the PCD service sets a value, it will check to ensure that the \r
811 size of the value being set is compatible with the Token's existing definition. \r
812 If it is not, an error will be returned.\r
813\r
814 @param[in] TokenNumber The PCD token number. \r
815 @param[in] Value The value to set for the PCD token.\r
816\r
817 @retval EFI_SUCCESS Procedure returned successfully.\r
818 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
819 being set was incompatible with a call to this function. \r
820 Use GetSize() to retrieve the size of the target data.\r
821 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
822 \r
823**/\r
824EFI_STATUS\r
825EFIAPI\r
826DxePcdSetBool (\r
827 IN UINTN TokenNumber,\r
828 IN BOOLEAN Value\r
829 )\r
830{\r
831 return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
832}\r
833\r
834/**\r
835 Sets an 8-bit value for a given PCD token.\r
836\r
837 When the PCD service sets a value, it will check to ensure that the \r
838 size of the value being set is compatible with the Token's existing definition. \r
839 If it is not, an error will be returned.\r
840\r
841 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
842 @param[in] ExTokenNumber The PCD token number. \r
843 @param[in] Value The value to set for the PCD token.\r
844\r
845 @retval EFI_SUCCESS Procedure returned successfully.\r
846 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
847 being set was incompatible with a call to this function. \r
848 Use GetSize() to retrieve the size of the target data.\r
849 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
850 \r
851**/\r
852EFI_STATUS\r
853EFIAPI\r
854DxePcdSet8Ex (\r
855 IN CONST EFI_GUID *Guid,\r
856 IN UINTN ExTokenNumber,\r
857 IN UINT8 Value\r
858 )\r
859{\r
860 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
861}\r
862\r
863/**\r
864 Sets an 16-bit value for a given PCD token.\r
865\r
866 When the PCD service sets a value, it will check to ensure that the \r
867 size of the value being set is compatible with the Token's existing definition. \r
868 If it is not, an error will be returned.\r
869\r
870 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
871 @param[in] ExTokenNumber The PCD token number. \r
872 @param[in] Value The value to set for the PCD token.\r
873\r
874 @retval EFI_SUCCESS Procedure returned successfully.\r
875 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
876 being set was incompatible with a call to this function. \r
877 Use GetSize() to retrieve the size of the target data.\r
878 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
879 \r
880**/\r
881EFI_STATUS\r
882EFIAPI\r
883DxePcdSet16Ex (\r
884 IN CONST EFI_GUID *Guid,\r
885 IN UINTN ExTokenNumber,\r
886 IN UINT16 Value\r
887 )\r
888{\r
889 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
890}\r
891\r
892/**\r
893 Sets an 32-bit value for a given PCD token.\r
894\r
895 When the PCD service sets a value, it will check to ensure that the \r
896 size of the value being set is compatible with the Token's existing definition. \r
897 If it is not, an error will be returned.\r
898\r
899 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
900 @param[in] ExTokenNumber The PCD token number. \r
901 @param[in] Value The value to set for the PCD token.\r
902\r
903 @retval EFI_SUCCESS Procedure returned successfully.\r
904 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
905 being set was incompatible with a call to this function. \r
906 Use GetSize() to retrieve the size of the target data.\r
907 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
908 \r
909**/\r
910EFI_STATUS\r
911EFIAPI\r
912DxePcdSet32Ex (\r
913 IN CONST EFI_GUID *Guid,\r
914 IN UINTN ExTokenNumber,\r
915 IN UINT32 Value\r
916 )\r
917{\r
918 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
919}\r
920\r
921/**\r
922 Sets an 64-bit value for a given PCD token.\r
923\r
924 When the PCD service sets a value, it will check to ensure that the \r
925 size of the value being set is compatible with the Token's existing definition. \r
926 If it is not, an error will be returned.\r
927\r
928 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
929 @param[in] ExTokenNumber The PCD token number. \r
930 @param[in] Value The value to set for the PCD token.\r
931\r
932 @retval EFI_SUCCESS Procedure returned successfully.\r
933 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
934 being set was incompatible with a call to this function. \r
935 Use GetSize() to retrieve the size of the target data.\r
936 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
937 \r
938**/\r
939EFI_STATUS\r
940EFIAPI\r
941DxePcdSet64Ex (\r
942 IN CONST EFI_GUID *Guid,\r
943 IN UINTN ExTokenNumber,\r
944 IN UINT64 Value\r
945 )\r
946{\r
947 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
948}\r
949\r
950/**\r
951 Sets a value of a specified size for a given PCD token.\r
952\r
953 When the PCD service sets a value, it will check to ensure that the \r
954 size of the value being set is compatible with the Token's existing definition. \r
955 If it is not, an error will be returned.\r
956\r
957 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
958 @param[in] ExTokenNumber The PCD token number. \r
959 @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token. \r
960 On input, if the SizeOfValue is greater than the maximum size supported \r
961 for this TokenNumber then the output value of SizeOfValue will reflect \r
962 the maximum size supported for this TokenNumber.\r
963 @param[in] Buffer The buffer to set for the PCD token.\r
964\r
965 @retval EFI_SUCCESS Procedure returned successfully.\r
966 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
967 being set was incompatible with a call to this function. \r
968 Use GetSize() to retrieve the size of the target data.\r
969 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
970 \r
971**/\r
972EFI_STATUS\r
973EFIAPI\r
974DxePcdSetPtrEx (\r
975 IN CONST EFI_GUID *Guid,\r
976 IN UINTN ExTokenNumber,\r
977 IN OUT UINTN *SizeOfBuffer,\r
978 IN VOID *Buffer\r
979 )\r
980{\r
981 return ExSetWorker(ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);\r
982}\r
983\r
984/**\r
985 Sets an Boolean value for a given PCD token.\r
986\r
987 When the PCD service sets a value, it will check to ensure that the \r
988 size of the value being set is compatible with the Token's existing definition. \r
989 If it is not, an error will be returned.\r
990\r
991 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
992 @param[in] ExTokenNumber The PCD token number. \r
993 @param[in] Value The value to set for the PCD token.\r
994\r
995 @retval EFI_SUCCESS Procedure returned successfully.\r
996 @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data \r
997 being set was incompatible with a call to this function. \r
998 Use GetSize() to retrieve the size of the target data.\r
999 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
1000 \r
1001**/\r
1002EFI_STATUS\r
1003EFIAPI\r
1004DxePcdSetBoolEx (\r
1005 IN CONST EFI_GUID *Guid,\r
1006 IN UINTN ExTokenNumber,\r
1007 IN BOOLEAN Value\r
1008 )\r
1009{\r
1010 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
1011}\r
1012\r
1013/**\r
1014 Specifies a function to be called anytime the value of a designated token is changed.\r
1015\r
1016 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
1017 @param[in] TokenNumber The PCD token number. \r
1018 @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. \r
1019\r
1020 @retval EFI_SUCCESS The PCD service has successfully established a call event \r
1021 for the CallBackToken requested.\r
1022 @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.\r
1023\r
1024**/\r
1025EFI_STATUS\r
1026EFIAPI\r
1027DxeRegisterCallBackOnSet (\r
1028 IN CONST EFI_GUID *Guid, OPTIONAL\r
1029 IN UINTN TokenNumber,\r
1030 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
1031 )\r
1032{\r
1033 EFI_STATUS Status;\r
1034 \r
1035 if (CallBackFunction == NULL) {\r
1036 return EFI_INVALID_PARAMETER;\r
1037 }\r
1038 //\r
1039 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
1040 //\r
1041 EfiAcquireLock (&mPcdDatabaseLock);\r
1042\r
1043 Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);\r
1044\r
1045 EfiReleaseLock (&mPcdDatabaseLock);\r
1046 \r
1047 return Status;\r
1048}\r
1049\r
1050/**\r
1051 Cancels a previously set callback function for a particular PCD token number.\r
1052\r
1053 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
1054 @param[in] TokenNumber The PCD token number. \r
1055 @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. \r
1056\r
1057 @retval EFI_SUCCESS The PCD service has successfully established a call event \r
1058 for the CallBackToken requested.\r
1059 @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.\r
1060\r
1061**/\r
1062EFI_STATUS\r
1063EFIAPI\r
1064DxeUnRegisterCallBackOnSet (\r
1065 IN CONST EFI_GUID *Guid, OPTIONAL\r
1066 IN UINTN TokenNumber,\r
1067 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
1068 )\r
1069{\r
1070 EFI_STATUS Status;\r
1071 \r
1072 if (CallBackFunction == NULL) {\r
1073 return EFI_INVALID_PARAMETER;\r
1074 }\r
1075\r
1076 //\r
1077 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
1078 //\r
1079 EfiAcquireLock (&mPcdDatabaseLock);\r
1080 \r
1081 Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);\r
1082\r
1083 EfiReleaseLock (&mPcdDatabaseLock);\r
1084 \r
1085 return Status;\r
1086}\r
1087\r
1088/**\r
1089 Retrieves the next valid token number in a given namespace. \r
1090 \r
1091 This is useful since the PCD infrastructure contains a sparse list of token numbers, \r
1092 and one cannot a priori know what token numbers are valid in the database. \r
1093 \r
1094 If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned. \r
1095 If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned. \r
1096 If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned. \r
1097 If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned. \r
1098 The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid. \r
1099 If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned. \r
1100 If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned. \r
1101 If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.\r
1102\r
1103\r
1104 @param[in] Guid The 128-bit unique value that designates the namespace from which to retrieve the next token. \r
1105 This is an optional parameter that may be NULL. If this parameter is NULL, then a request is \r
1106 being made to retrieve tokens from the default token space.\r
1107 @param[in, out] TokenNumber \r
1108 A pointer to the PCD token number to use to find the subsequent token number. \r
1109\r
1110 @retval EFI_SUCCESS The PCD service has retrieved the next valid token number.\r
1111 @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.\r
1112\r
1113**/\r
1114EFI_STATUS\r
1115EFIAPI\r
1116DxePcdGetNextToken (\r
1117 IN CONST EFI_GUID *Guid, OPTIONAL\r
1118 IN OUT UINTN *TokenNumber\r
1119 )\r
1120{\r
1121 EFI_STATUS Status;\r
1122 BOOLEAN PeiExMapTableEmpty;\r
1123 BOOLEAN DxeExMapTableEmpty;\r
1124\r
1125 Status = EFI_NOT_FOUND;\r
1126 PeiExMapTableEmpty = mPeiExMapTableEmpty;\r
1127 DxeExMapTableEmpty = mDxeExMapTableEmpty;\r
1128\r
1129 //\r
1130 // Scan the local token space\r
1131 //\r
1132 if (Guid == NULL) {\r
1133 // EBC compiler is very choosy. It may report warning about comparison\r
1134 // between UINTN and 0 . So we add 1 in each size of the \r
1135 // comparison.\r
1136 if (((*TokenNumber + 1 > mPeiNexTokenCount + 1) && (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||\r
1137 ((*TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1)))) {\r
1138 return EFI_NOT_FOUND;\r
1139 }\r
1140 \r
1141 (*TokenNumber)++;\r
1142 if ((*TokenNumber + 1 > mPeiNexTokenCount + 1) &&\r
1143 (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) {\r
1144 //\r
1145 // The first Non-Ex type Token Number for DXE PCD \r
1146 // database is mPeiLocalTokenCount + 1\r
1147 //\r
1148 if (mDxeNexTokenCount > 0) {\r
1149 *TokenNumber = mPeiLocalTokenCount + 1;\r
1150 } else {\r
1151 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
1152 return EFI_NOT_FOUND;\r
1153 }\r
1154 } else if (*TokenNumber + 1 > mDxeNexTokenCount + mPeiLocalTokenCount + 1) {\r
1155 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
1156 return EFI_NOT_FOUND;\r
1157 }\r
1158 return EFI_SUCCESS;\r
1159 }\r
1160\r
1161 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {\r
1162 return EFI_NOT_FOUND;\r
1163 }\r
1164\r
1165 if (!PeiExMapTableEmpty) {\r
1166 Status = ExGetNextTokeNumber (\r
1167 Guid,\r
1168 TokenNumber,\r
1169 (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset),\r
1170 mPeiGuidTableSize,\r
1171 (DYNAMICEX_MAPPING *)((UINT8 *) mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),\r
1172 mPeiExMapppingTableSize\r
1173 );\r
1174 }\r
1175\r
1176 if (Status == EFI_SUCCESS) {\r
1177 return Status;\r
1178 }\r
1179\r
1180 if (!DxeExMapTableEmpty) {\r
1181 Status = ExGetNextTokeNumber (\r
1182 Guid,\r
1183 TokenNumber,\r
1184 (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset),\r
1185 mDxeGuidTableSize,\r
1186 (DYNAMICEX_MAPPING *)((UINT8 *) mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),\r
1187 mDxeExMapppingTableSize\r
1188 );\r
1189 }\r
1190\r
1191 return Status;\r
1192}\r
1193\r
1194/**\r
1195 Get all token space guid table which is different with given token space guid.\r
1196\r
1197 @param ExMapTableSize The size of ExMapTable in item\r
1198 @param ExMapTable Token space guid table that want to be scaned.\r
1199 @param GuidTable Guid table\r
1200\r
1201 @return all token space guid table which is different with given token space guid.\r
1202\r
1203**/\r
1204EFI_GUID **\r
1205GetDistinctTokenSpace (\r
1206 IN OUT UINTN *ExMapTableSize,\r
1207 IN DYNAMICEX_MAPPING *ExMapTable,\r
1208 IN EFI_GUID *GuidTable\r
1209 )\r
1210{\r
1211 EFI_GUID **DistinctTokenSpace;\r
1212 UINTN OldGuidIndex;\r
1213 UINTN TsIdx;\r
1214 UINTN TempTsIdx;\r
1215 UINTN Idx;\r
1216 BOOLEAN Match;\r
1217\r
1218 DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));\r
1219 ASSERT (DistinctTokenSpace != NULL);\r
1220\r
1221 TsIdx = 0;\r
1222 OldGuidIndex = ExMapTable[0].ExGuidIndex;\r
1223 DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];\r
1224 for (Idx = 1; Idx < *ExMapTableSize; Idx++) {\r
1225 Match = FALSE;\r
1226 OldGuidIndex = ExMapTable[Idx].ExGuidIndex;\r
1227 for (TempTsIdx = 0; TempTsIdx <= TsIdx; TempTsIdx++) {\r
1228 if (&GuidTable[OldGuidIndex] == DistinctTokenSpace[TempTsIdx]) {\r
1229 //\r
1230 // Have recorded this GUID.\r
1231 //\r
1232 Match = TRUE;\r
1233 break;\r
1234 }\r
1235 }\r
1236 if (!Match) {\r
1237 DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];\r
1238 }\r
1239 }\r
1240\r
1241 //\r
1242 // The total number of Distinct Token Space\r
1243 // is TsIdx + 1 because we use TsIdx as a index\r
1244 // to the DistinctTokenSpace[]\r
1245 //\r
1246 *ExMapTableSize = TsIdx + 1;\r
1247 return DistinctTokenSpace;\r
1248 \r
1249}\r
1250 \r
1251/**\r
1252 Retrieves the next valid PCD token namespace for a given namespace.\r
1253\r
1254 Gets the next valid token namespace for a given namespace. This is useful to traverse the valid\r
1255 token namespaces on a platform.\r
1256\r
1257 @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token\r
1258 namespace from which the search will start. On output, it designates the next valid\r
1259 token namespace on the platform. If *Guid is NULL, then the GUID of the first token\r
1260 space of the current platform is returned. If the search cannot locate the next valid\r
1261 token namespace, an error is returned and the value of *Guid is undefined.\r
1262 \r
1263 @retval EFI_SUCCESS The PCD service retrieved the value requested.\r
1264 @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace.\r
1265\r
1266**/\r
1267EFI_STATUS\r
1268EFIAPI\r
1269DxePcdGetNextTokenSpace (\r
1270 IN OUT CONST EFI_GUID **Guid\r
1271 )\r
1272{\r
1273 UINTN Idx;\r
1274 UINTN Idx2;\r
1275 UINTN Idx3;\r
1276 UINTN PeiTokenSpaceTableSize;\r
1277 UINTN DxeTokenSpaceTableSize;\r
1278 EFI_GUID **PeiTokenSpaceTable;\r
1279 EFI_GUID **DxeTokenSpaceTable;\r
1280 BOOLEAN Match;\r
1281 BOOLEAN PeiExMapTableEmpty;\r
1282 BOOLEAN DxeExMapTableEmpty;\r
1283\r
1284 ASSERT (Guid != NULL);\r
1285 \r
1286 PeiExMapTableEmpty = mPeiExMapTableEmpty;\r
1287 DxeExMapTableEmpty = mDxeExMapTableEmpty;\r
1288\r
1289 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {\r
1290 return EFI_NOT_FOUND;\r
1291 }\r
1292 \r
1293 if (TmpTokenSpaceBuffer[0] == NULL) {\r
1294 PeiTokenSpaceTableSize = 0;\r
1295\r
1296 if (!PeiExMapTableEmpty) {\r
1297 PeiTokenSpaceTableSize = mPeiExMapppingTableSize / sizeof(DYNAMICEX_MAPPING);\r
1298 PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize,\r
1299 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),\r
1300 (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset)\r
1301 );\r
1302 CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize);\r
1303 TmpTokenSpaceBufferCount = PeiTokenSpaceTableSize;\r
1304 FreePool (PeiTokenSpaceTable);\r
1305 }\r
1306\r
1307 if (!DxeExMapTableEmpty) {\r
1308 DxeTokenSpaceTableSize = mDxeExMapppingTableSize / sizeof(DYNAMICEX_MAPPING);\r
1309 DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize,\r
1310 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),\r
1311 (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset)\r
1312 );\r
1313\r
1314 //\r
1315 // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable\r
1316 //\r
1317 for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {\r
1318 Match = FALSE;\r
1319 for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {\r
1320 if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {\r
1321 Match = TRUE;\r
1322 break;\r
1323 }\r
1324 }\r
1325 if (!Match) {\r
1326 TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];\r
1327 }\r
1328 }\r
1329\r
1330 TmpTokenSpaceBufferCount = Idx3;\r
1331 FreePool (DxeTokenSpaceTable);\r
1332 }\r
1333 }\r
1334\r
1335 if (*Guid == NULL) {\r
1336 *Guid = TmpTokenSpaceBuffer[0];\r
1337 return EFI_SUCCESS;\r
1338 }\r
1339 \r
1340 for (Idx = 0; Idx < TmpTokenSpaceBufferCount; Idx++) {\r
1341 if (CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {\r
1342 if (Idx == TmpTokenSpaceBufferCount - 1) {\r
1343 //\r
1344 // It has been the last token namespace.\r
1345 //\r
1346 *Guid = NULL;\r
1347 return EFI_NOT_FOUND;\r
1348 } else {\r
1349 Idx++;\r
1350 *Guid = TmpTokenSpaceBuffer[Idx];\r
1351 return EFI_SUCCESS;\r
1352 }\r
1353 }\r
1354 }\r
1355\r
1356 return EFI_NOT_FOUND;\r
1357}\r
1358\r
1359\r