]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PCD/Dxe/Service.c
Allocate aligned buffer to satisfy the IoAlign requirement of high level protocol.
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Service.c
CommitLineData
80408db0 1/** @file\r
2ab6330e 2 Help functions used by PCD DXE driver.\r
80408db0 3\r
e5eed7d3
HT
4Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
80408db0 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
80408db0 13**/\r
80408db0 14\r
15#include "Service.h"\r
16\r
b07a5b68 17PCD_DATABASE *mPcdDatabase;\r
80408db0 18\r
b07a5b68 19LIST_ENTRY *mCallbackFnTable;\r
80408db0 20\r
2ab6330e 21/**\r
22 Get the PCD entry pointer in PCD database.\r
23 \r
24 This routine will visit PCD database to find the PCD entry according to given\r
25 token number. The given token number is autogened by build tools and it will be \r
26 translated to local token number. Local token number contains PCD's type and \r
27 offset of PCD entry in PCD database.\r
28\r
29 @param TokenNumber Token's number, it is autogened by build tools\r
30 @param GetSize The size of token's value\r
31\r
32 @return PCD entry pointer in PCD database\r
33\r
34**/\r
80408db0 35VOID *\r
36GetWorker (\r
2ab6330e 37 IN UINTN TokenNumber,\r
38 IN UINTN GetSize\r
80408db0 39 )\r
40{\r
41 UINT32 *LocalTokenNumberTable;\r
42 EFI_GUID *GuidTable;\r
d0965169 43 UINT8 *StringTable;\r
80408db0 44 EFI_GUID *Guid;\r
45 UINT16 *Name;\r
46 VARIABLE_HEAD *VariableHead;\r
47 UINT8 *VaraiableDefaultBuffer;\r
48 UINT8 *Data;\r
49 VPD_HEAD *VpdHead;\r
50 UINT8 *PcdDb;\r
51 VOID *RetPtr;\r
52 UINTN MaxSize;\r
53 UINTN TmpTokenNumber;\r
54 UINTN DataSize;\r
55 EFI_STATUS Status;\r
56 UINT32 LocalTokenNumber;\r
57 UINT32 Offset;\r
58 UINT16 StringTableIdx; \r
59 BOOLEAN IsPeiDb;\r
60\r
61 //\r
62 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
63 //\r
64 EfiAcquireLock (&mPcdDatabaseLock);\r
65\r
66 RetPtr = NULL;\r
67 //\r
68 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
69 // We have to decrement TokenNumber by 1 to make it usable\r
70 // as the array index.\r
71 //\r
72 TokenNumber--;\r
73\r
74 TmpTokenNumber = TokenNumber;\r
75 \r
76 //\r
77 // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.\r
78 // It could be zero. EBC compiler is very choosy. It may\r
79 // report warning. So we add 1 in each size of the \r
80 // comparison.\r
81 //\r
82 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
83\r
84 ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));\r
85\r
86 // EBC compiler is very choosy. It may report warning about comparison\r
87 // between UINTN and 0 . So we add 1 in each size of the \r
88 // comparison.\r
89 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
90\r
91 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
92 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
93\r
94 TokenNumber = IsPeiDb ? TokenNumber :\r
95 TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
96\r
97 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
98 \r
99 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
100 if (GetSize == 0) {\r
101 GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
102 } else {\r
103 MaxSize = GetSize;\r
104 }\r
105 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
106 }\r
107\r
108 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
309e3122 109 \r
110 if (IsPeiDb) {\r
d0965169 111 StringTable = (UINT8 *) (&mPcdDatabase->PeiDb.Init.StringTable[0]);\r
309e3122 112 } else {\r
d0965169 113 StringTable = (UINT8 *) (&mPcdDatabase->DxeDb.Init.StringTable[0]);\r
309e3122 114 }\r
115 \r
80408db0 116 \r
117 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
118 \r
119 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
120 case PCD_TYPE_VPD:\r
121 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);\r
188e4e84 122 RetPtr = (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);\r
80408db0 123 break;\r
124 \r
6ac15f7c 125 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 126 case PCD_TYPE_HII:\r
309e3122 127 if (IsPeiDb) {\r
128 GuidTable = (EFI_GUID *) (&mPcdDatabase->PeiDb.Init.GuidTable[0]);\r
129 } else {\r
130 GuidTable = (EFI_GUID *) (&mPcdDatabase->DxeDb.Init.GuidTable[0]);\r
131 }\r
80408db0 132 \r
133 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
1fef733c 134 Guid = GuidTable + VariableHead->GuidTableIndex;\r
d0965169 135 Name = (UINT16*)(StringTable + VariableHead->StringIndex);\r
6ac15f7c 136 \r
137 if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
138 //\r
139 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of \r
140 // string array in string table.\r
141 //\r
142 StringTableIdx = *(UINT16*)((UINT8 *) PcdDb + VariableHead->DefaultValueOffset); \r
143 VaraiableDefaultBuffer = (VOID *) (StringTable + StringTableIdx); \r
144 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
145 if (Status == EFI_SUCCESS) {\r
146 if (GetSize == 0) {\r
147 //\r
148 // It is a pointer type. So get the MaxSize reserved for\r
149 // this PCD entry.\r
150 //\r
151 GetPtrTypeSize (TmpTokenNumber, &GetSize);\r
152 }\r
153 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);\r
154 FreePool (Data);\r
80408db0 155 }\r
6ac15f7c 156 RetPtr = (VOID *) VaraiableDefaultBuffer; \r
157 } else {\r
158 VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;\r
159 \r
160 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
161 if (Status == EFI_SUCCESS) {\r
162 if (GetSize == 0) {\r
163 //\r
164 // It is a pointer type. So get the MaxSize reserved for\r
165 // this PCD entry.\r
166 //\r
167 GetPtrTypeSize (TmpTokenNumber, &GetSize);\r
168 }\r
169 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);\r
170 FreePool (Data);\r
171 }\r
172 //\r
173 // If the operation is successful, we copy the data\r
174 // to the default value buffer in the PCD Database.\r
175 // So that we can free the Data allocated in GetHiiVariable.\r
176 //\r
177 //\r
178 // If the operation is not successful, \r
179 // Return 1) either the default value specified by Platform Integrator \r
180 // 2) Or the value Set by a PCD set operation.\r
181 //\r
182 RetPtr = (VOID *) VaraiableDefaultBuffer;\r
80408db0 183 }\r
80408db0 184 break;\r
185\r
186 case PCD_TYPE_STRING:\r
2ef9435a 187 StringTableIdx = *(UINT16*)((UINT8 *) PcdDb + Offset);\r
1fef733c 188 RetPtr = (VOID *) (StringTable + StringTableIdx);\r
80408db0 189 break;\r
190\r
191 case PCD_TYPE_DATA:\r
192 RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);\r
193 break;\r
194\r
195 default:\r
196 ASSERT (FALSE);\r
197 break;\r
198 \r
199 }\r
200\r
201 EfiReleaseLock (&mPcdDatabaseLock);\r
202 \r
203 return RetPtr;\r
204 \r
205}\r
206\r
2ab6330e 207/**\r
208 Register the callback function for a PCD entry.\r
209\r
210 This routine will register a callback function to a PCD entry by given token number\r
211 and token space guid.\r
212 \r
213 @param TokenNumber PCD token's number, it is autogened by build tools.\r
214 @param Guid PCD token space's guid, \r
215 if not NULL, this PCD is dynamicEx type PCD.\r
216 @param CallBackFunction Callback function pointer\r
80408db0 217\r
2ab6330e 218 @return EFI_SUCCESS Always success for registering callback function.\r
80408db0 219\r
2ab6330e 220**/\r
80408db0 221EFI_STATUS\r
222DxeRegisterCallBackWorker (\r
223 IN UINTN TokenNumber,\r
2ab6330e 224 IN CONST EFI_GUID *Guid, OPTIONAL\r
80408db0 225 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
226)\r
227{\r
228 CALLBACK_FN_ENTRY *FnTableEntry;\r
229 LIST_ENTRY *ListHead;\r
230 LIST_ENTRY *ListNode;\r
231\r
232 if (Guid != NULL) {\r
233 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
234 }\r
235\r
236 //\r
237 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
238 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 239 // as the array index of mCallbackFnTable[].\r
80408db0 240 //\r
b07a5b68 241 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 242 ListNode = GetFirstNode (ListHead);\r
243\r
244 while (ListNode != ListHead) {\r
245 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
246\r
247 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
248 //\r
249 // We only allow a Callback function to be register once\r
250 // for a TokenNumber. So just return EFI_SUCCESS\r
251 //\r
252 return EFI_SUCCESS;\r
253 }\r
254 ListNode = GetNextNode (ListHead, ListNode);\r
255 }\r
256\r
257 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));\r
258 ASSERT (FnTableEntry != NULL);\r
259\r
260 FnTableEntry->CallbackFn = CallBackFunction;\r
261 InsertTailList (ListHead, &FnTableEntry->Node);\r
262 \r
263 return EFI_SUCCESS;\r
264}\r
265\r
2ab6330e 266/**\r
267 UnRegister the callback function for a PCD entry.\r
80408db0 268\r
2ab6330e 269 This routine will unregister a callback function to a PCD entry by given token number\r
270 and token space guid.\r
80408db0 271\r
2ab6330e 272 @param TokenNumber PCD token's number, it is autogened by build tools.\r
273 @param Guid PCD token space's guid.\r
274 if not NULL, this PCD is dynamicEx type PCD.\r
275 @param CallBackFunction Callback function pointer\r
80408db0 276\r
2ab6330e 277 @retval EFI_SUCCESS Callback function is success to be unregister.\r
278 @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.\r
279**/\r
80408db0 280EFI_STATUS\r
281DxeUnRegisterCallBackWorker (\r
282 IN UINTN TokenNumber,\r
2ab6330e 283 IN CONST EFI_GUID *Guid, OPTIONAL\r
80408db0 284 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
285)\r
286{\r
287 CALLBACK_FN_ENTRY *FnTableEntry;\r
288 LIST_ENTRY *ListHead;\r
289 LIST_ENTRY *ListNode;\r
290\r
291 if (Guid != NULL) {\r
292 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
293 }\r
294\r
295 //\r
296 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
297 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 298 // as the array index of mCallbackFnTable[].\r
80408db0 299 //\r
b07a5b68 300 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 301 ListNode = GetFirstNode (ListHead);\r
302\r
303 while (ListNode != ListHead) {\r
304 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
305\r
306 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
307 //\r
308 // We only allow a Callback function to be register once\r
309 // for a TokenNumber. So we can safely remove the Node from\r
310 // the Link List and return EFI_SUCCESS.\r
311 //\r
312 RemoveEntryList (ListNode);\r
313 FreePool (FnTableEntry);\r
314 \r
315 return EFI_SUCCESS;\r
316 }\r
317 ListNode = GetNextNode (ListHead, ListNode);\r
318 }\r
319\r
320 return EFI_INVALID_PARAMETER;\r
321}\r
322\r
2ab6330e 323/**\r
324 Get next token number in given token space.\r
325 \r
326 This routine is used for dynamicEx type PCD. It will firstly scan token space\r
327 table to get token space according to given token space guid. Then scan given \r
328 token number in found token space, if found, then return next token number in \r
329 this token space.\r
330\r
331 @param Guid Token space guid. Next token number will be scaned in \r
332 this token space.\r
333 @param TokenNumber Token number. \r
334 If PCD_INVALID_TOKEN_NUMBER, return first token number in \r
335 token space table.\r
336 If not PCD_INVALID_TOKEN_NUMBER, return next token number\r
337 in token space table.\r
338 @param GuidTable Token space guid table. It will be used for scan token space\r
339 by given token space guid.\r
340 @param SizeOfGuidTable The size of guid table.\r
341 @param ExMapTable DynamicEx token number mapping table.\r
342 @param SizeOfExMapTable The size of dynamicEx token number mapping table.\r
343\r
344 @retval EFI_NOT_FOUND Can not given token space or token number.\r
345 @retval EFI_SUCCESS Success to get next token number.\r
80408db0 346\r
2ab6330e 347**/\r
80408db0 348EFI_STATUS\r
349ExGetNextTokeNumber (\r
350 IN CONST EFI_GUID *Guid,\r
351 IN OUT UINTN *TokenNumber,\r
352 IN EFI_GUID *GuidTable,\r
353 IN UINTN SizeOfGuidTable,\r
354 IN DYNAMICEX_MAPPING *ExMapTable,\r
355 IN UINTN SizeOfExMapTable\r
356 )\r
357{\r
358 EFI_GUID *MatchGuid;\r
2ab6330e 359 UINTN Index;\r
80408db0 360 UINTN GuidTableIdx;\r
361 BOOLEAN Found;\r
362\r
2ab6330e 363 //\r
364 // Scan token space guid \r
365 // \r
80408db0 366 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);\r
367 if (MatchGuid == NULL) {\r
368 return EFI_NOT_FOUND;\r
369 }\r
370\r
2ab6330e 371 //\r
372 // Find the token space table in dynamicEx mapping table.\r
373 //\r
80408db0 374 Found = FALSE;\r
375 GuidTableIdx = MatchGuid - GuidTable;\r
2ab6330e 376 for (Index = 0; Index < SizeOfExMapTable; Index++) {\r
377 if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
80408db0 378 Found = TRUE;\r
379 break;\r
380 }\r
381 }\r
382\r
383 if (Found) {\r
2ab6330e 384 //\r
385 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first\r
386 // token number in found token space.\r
387 //\r
80408db0 388 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
2ab6330e 389 *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
80408db0 390 return EFI_SUCCESS;\r
391 }\r
392\r
2ab6330e 393 for ( ; Index < SizeOfExMapTable; Index++) {\r
394 if (ExMapTable[Index].ExTokenNumber == *TokenNumber) {\r
395 Index ++;\r
396 if (Index == SizeOfExMapTable) {\r
80408db0 397 //\r
398 // Exceed the length of ExMap Table\r
399 //\r
400 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
401 return EFI_SUCCESS;\r
2ab6330e 402 } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
80408db0 403 //\r
404 // Found the next match\r
405 //\r
2ab6330e 406 *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
80408db0 407 return EFI_SUCCESS;\r
408 } else {\r
409 //\r
410 // Guid has been changed. It is the next Token Space Guid.\r
411 // We should flag no more TokenNumber.\r
412 //\r
413 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
414 return EFI_SUCCESS;\r
415 }\r
416 }\r
417 }\r
418 }\r
419 \r
420 return EFI_NOT_FOUND;\r
421}\r
80408db0 422\r
423\r
2ab6330e 424/**\r
425 Initialize the PCD database in DXE phase.\r
426 \r
427 PCD database in DXE phase also contains PCD database in PEI phase which is copied\r
428 from GUID Hob.\r
80408db0 429\r
2ab6330e 430**/\r
80408db0 431VOID\r
432BuildPcdDxeDataBase (\r
433 VOID\r
434 )\r
435{\r
436 PEI_PCD_DATABASE *PeiDatabase;\r
437 EFI_HOB_GUID_TYPE *GuidHob;\r
2ab6330e 438 UINTN Index;\r
80408db0 439\r
440 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));\r
441 ASSERT (mPcdDatabase != NULL);\r
442\r
443 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
444 if (GuidHob != NULL) {\r
445\r
446 //\r
447 // We will copy over the PEI phase's PCD Database.\r
448 // \r
449 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM\r
450 // should not be included at all. So the GuidHob could\r
451 // be NULL. If it is NULL, we just copy over the DXE Default\r
452 // Value to PCD Database.\r
453 //\r
454 \r
455 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
456 //\r
457 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE\r
458 //\r
459 CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));\r
460 }\r
461\r
462 //\r
463 // Copy PCD Entries with default value to PCD DATABASE\r
464 //\r
465 CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));\r
466\r
467\r
468 //\r
469 // Initialized the Callback Function Table\r
470 //\r
471\r
472 mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));\r
3fd8027e 473 ASSERT(mCallbackFnTable != NULL);\r
80408db0 474 \r
475 // EBC compiler is very choosy. It may report warning about comparison\r
476 // between UINTN and 0 . So we add 1 in each size of the \r
477 // comparison.\r
2ab6330e 478 for (Index = 0; Index + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Index++) {\r
479 InitializeListHead (&mCallbackFnTable[Index]);\r
80408db0 480 }\r
80408db0 481}\r
482\r
2ab6330e 483/**\r
484 Get Variable which contains HII type PCD entry.\r
80408db0 485\r
2ab6330e 486 @param VariableGuid Variable's guid\r
487 @param VariableName Variable's unicode name string\r
488 @param VariableData Variable's data pointer, \r
489 @param VariableSize Variable's size.\r
80408db0 490\r
2ab6330e 491 @return the status of gRT->GetVariable\r
492**/\r
80408db0 493EFI_STATUS\r
494GetHiiVariable (\r
495 IN EFI_GUID *VariableGuid,\r
496 IN UINT16 *VariableName,\r
497 OUT UINT8 **VariableData,\r
498 OUT UINTN *VariableSize\r
499 )\r
500{\r
501 UINTN Size;\r
502 EFI_STATUS Status;\r
503 UINT8 *Buffer;\r
504\r
505 Size = 0;\r
506 Buffer = NULL;\r
507 \r
2ab6330e 508 //\r
509 // Firstly get the real size of HII variable\r
510 //\r
80408db0 511 Status = gRT->GetVariable (\r
512 (UINT16 *)VariableName,\r
513 VariableGuid,\r
514 NULL,\r
515 &Size,\r
516 Buffer\r
517 );\r
518 \r
2ab6330e 519 //\r
520 // Allocate buffer to hold whole variable data according to variable size.\r
521 //\r
80408db0 522 if (Status == EFI_BUFFER_TOO_SMALL) {\r
523 Buffer = (UINT8 *) AllocatePool (Size);\r
524\r
525 ASSERT (Buffer != NULL);\r
526\r
527 Status = gRT->GetVariable (\r
528 VariableName,\r
529 VariableGuid,\r
530 NULL,\r
531 &Size,\r
532 Buffer\r
533 );\r
534\r
535 ASSERT (Status == EFI_SUCCESS);\r
536 *VariableData = Buffer;\r
537 *VariableSize = Size;\r
538 }\r
539\r
540 return Status;\r
541}\r
542\r
2ab6330e 543/**\r
544 Find the local token number according to system SKU ID.\r
545\r
546 @param LocalTokenNumber PCD token number\r
547 @param Size The size of PCD entry.\r
548 @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.\r
549 If False, the PCD entry is initialized in DXE phase.\r
550\r
551 @return Token number according to system SKU ID.\r
80408db0 552\r
2ab6330e 553**/\r
80408db0 554UINT32\r
555GetSkuEnabledTokenNumber (\r
556 UINT32 LocalTokenNumber,\r
557 UINTN Size,\r
558 BOOLEAN IsPeiDb\r
559 ) \r
560{\r
561 SKU_HEAD *SkuHead;\r
562 SKU_ID *SkuIdTable;\r
2ab6330e 563 INTN Index;\r
80408db0 564 UINT8 *Value;\r
565 SKU_ID *PhaseSkuIdTable;\r
566 UINT8 *PcdDb;\r
567\r
568 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
569\r
570 PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;\r
571\r
572 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
573 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
574\r
575 PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :\r
576 mPcdDatabase->DxeDb.Init.SkuIdTable;\r
577 \r
578 SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];\r
579 \r
2ab6330e 580 //\r
581 // Find the current system's SKU ID entry in SKU ID table.\r
582 //\r
583 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
584 if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[Index + 1]) {\r
80408db0 585 break;\r
586 }\r
587 }\r
2ab6330e 588 ASSERT (Index < SkuIdTable[0]);\r
80408db0 589\r
590 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
591 case PCD_TYPE_VPD:\r
2ab6330e 592 Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);\r
80408db0 593 return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);\r
594\r
595 case PCD_TYPE_HII:\r
2ab6330e 596 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
80408db0 597 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);\r
598\r
599 case PCD_TYPE_STRING:\r
2ab6330e 600 Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);\r
80408db0 601 return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);\r
602 \r
603 case PCD_TYPE_DATA:\r
2ab6330e 604 Value += Size * Index;\r
80408db0 605 return (UINT32) (Value - PcdDb);\r
606\r
607 default:\r
608 ASSERT (FALSE);\r
609 }\r
610\r
611 ASSERT (FALSE);\r
612\r
613 return 0;\r
614 \r
615}\r
616\r
2ab6330e 617/**\r
618 Invoke the callback function when dynamic PCD entry was set, if this PCD entry \r
619 has registered callback function.\r
80408db0 620\r
2ab6330e 621 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx\r
622 type PCD.\r
623 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type\r
624 PCD.\r
625 @param TokenNumber PCD token number generated by build tools.\r
626 @param Data Value want to be set for this PCD entry\r
627 @param Size The size of value\r
80408db0 628\r
2ab6330e 629**/\r
80408db0 630VOID\r
631InvokeCallbackOnSet (\r
632 UINT32 ExTokenNumber,\r
633 CONST EFI_GUID *Guid, OPTIONAL\r
634 UINTN TokenNumber,\r
635 VOID *Data,\r
636 UINTN Size\r
637 )\r
638{\r
639 CALLBACK_FN_ENTRY *FnTableEntry;\r
640 LIST_ENTRY *ListHead;\r
641 LIST_ENTRY *ListNode;\r
642\r
643 //\r
644 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
645 // We have to decrement TokenNumber by 1 to make it usable\r
b07a5b68 646 // as the array index of mCallbackFnTable[].\r
80408db0 647 //\r
b07a5b68 648 ListHead = &mCallbackFnTable[TokenNumber - 1];\r
80408db0 649 ListNode = GetFirstNode (ListHead);\r
650\r
651 while (ListNode != ListHead) {\r
b07a5b68 652 FnTableEntry = CR_FNENTRY_FROM_LISTNODE (ListNode, CALLBACK_FN_ENTRY, Node);\r
80408db0 653\r
654 FnTableEntry->CallbackFn(Guid, \r
655 (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
656 Data,\r
657 Size);\r
658 \r
659 ListNode = GetNextNode (ListHead, ListNode);\r
660 }\r
661 \r
662 return;\r
663}\r
664\r
665\r
2ab6330e 666/**\r
667 Wrapper function for setting non-pointer type value for a PCD entry.\r
668\r
669 @param TokenNumber Pcd token number autogenerated by build tools.\r
670 @param Data Value want to be set for PCD entry\r
671 @param Size Size of value.\r
672\r
673 @return status of SetWorker.\r
674\r
675**/\r
80408db0 676EFI_STATUS\r
677SetValueWorker (\r
678 IN UINTN TokenNumber,\r
679 IN VOID *Data,\r
680 IN UINTN Size\r
681 )\r
682{\r
683 return SetWorker (TokenNumber, Data, &Size, FALSE);\r
684}\r
685\r
686\r
2ab6330e 687/**\r
688 Set value for an PCD entry\r
689\r
690 @param TokenNumber Pcd token number autogenerated by build tools.\r
691 @param Data Value want to be set for PCD entry\r
692 @param Size Size of value.\r
693 @param PtrType If TRUE, the type of PCD entry's value is Pointer.\r
694 If False, the type of PCD entry's value is not Pointer.\r
695\r
696 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.\r
697 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.\r
149fb6d6 698 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database. \r
2ab6330e 699 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in\r
700 range of UINT8, UINT16, UINT32, UINT64\r
701 @retval EFI_NOT_FOUND Can not find the PCD type according to token number. \r
702**/\r
80408db0 703EFI_STATUS\r
704SetWorker (\r
705 IN UINTN TokenNumber,\r
706 IN VOID *Data,\r
707 IN OUT UINTN *Size,\r
708 IN BOOLEAN PtrType\r
709 )\r
710{\r
711 UINT32 *LocalTokenNumberTable;\r
712 BOOLEAN IsPeiDb;\r
713 UINT32 LocalTokenNumber;\r
714 EFI_GUID *GuidTable;\r
d0965169 715 UINT8 *StringTable;\r
80408db0 716 EFI_GUID *Guid;\r
717 UINT16 *Name;\r
718 UINTN VariableOffset;\r
719 VOID *InternalData;\r
720 VARIABLE_HEAD *VariableHead;\r
721 UINTN Offset;\r
722 UINT8 *PcdDb;\r
723 EFI_STATUS Status;\r
724 UINTN MaxSize;\r
725 UINTN TmpTokenNumber;\r
726\r
80408db0 727 //\r
728 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
729 // We have to decrement TokenNumber by 1 to make it usable\r
730 // as the array index.\r
731 //\r
732 TokenNumber--;\r
733\r
734 TmpTokenNumber = TokenNumber;\r
735 \r
2ab6330e 736 //\r
80408db0 737 // EBC compiler is very choosy. It may report warning about comparison\r
738 // between UINTN and 0 . So we add 1 in each size of the \r
739 // comparison.\r
2ab6330e 740 //\r
80408db0 741 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
742\r
8ec8bed4 743 if (PtrType) {\r
744 if (*Size > DxePcdGetSize (TokenNumber + 1)) {\r
745 return EFI_INVALID_PARAMETER;\r
746 }\r
747 } else {\r
748 if (*Size != DxePcdGetSize (TokenNumber + 1)) {\r
749 return EFI_INVALID_PARAMETER;\r
750 }\r
80408db0 751 }\r
b07a5b68 752\r
2ab6330e 753 //\r
80408db0 754 // EBC compiler is very choosy. It may report warning about comparison\r
755 // between UINTN and 0 . So we add 1 in each size of the \r
756 // comparison.\r
2ab6330e 757 //\r
b07a5b68 758 if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||\r
759 (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {\r
760 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
761 }\r
80408db0 762\r
b07a5b68 763 //\r
764 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
765 //\r
766 EfiAcquireLock (&mPcdDatabaseLock);\r
80408db0 767\r
2ab6330e 768 //\r
80408db0 769 // EBC compiler is very choosy. It may report warning about comparison\r
770 // between UINTN and 0 . So we add 1 in each size of the \r
771 // comparison.\r
2ab6330e 772 //\r
b07a5b68 773 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
774\r
775 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
776 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
80408db0 777\r
778 TokenNumber = IsPeiDb ? TokenNumber\r
779 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
780\r
781 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
782 \r
783 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
784 if (PtrType) {\r
785 GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
786 } else {\r
787 MaxSize = *Size;\r
788 }\r
789 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
790 }\r
791\r
792 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
793\r
794 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
795\r
309e3122 796 if (IsPeiDb) {\r
d0965169 797 StringTable = (UINT8 *) (&mPcdDatabase->PeiDb.Init.StringTable[0]);\r
309e3122 798 } else {\r
d0965169 799 StringTable = (UINT8 *) (&mPcdDatabase->DxeDb.Init.StringTable[0]);\r
309e3122 800 }\r
801\r
80408db0 802 \r
803 InternalData = PcdDb + Offset;\r
804\r
805 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
806 case PCD_TYPE_VPD:\r
807 ASSERT (FALSE);\r
808 Status = EFI_INVALID_PARAMETER;\r
809 break;\r
810 \r
811 case PCD_TYPE_STRING:\r
812 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
7076244e 813 CopyMem (StringTable + *((UINT16 *)InternalData), Data, *Size);\r
80408db0 814 Status = EFI_SUCCESS;\r
815 } else {\r
816 Status = EFI_INVALID_PARAMETER;\r
817 }\r
818 break;\r
819\r
6ac15f7c 820 case PCD_TYPE_HII|PCD_TYPE_STRING:\r
80408db0 821 case PCD_TYPE_HII:\r
822 if (PtrType) {\r
823 if (!SetPtrTypeSize (TmpTokenNumber, Size)) {\r
824 Status = EFI_INVALID_PARAMETER;\r
825 break;\r
826 }\r
827 }\r
828 \r
309e3122 829 if (IsPeiDb) {\r
830 GuidTable = (EFI_GUID *) (&mPcdDatabase->PeiDb.Init.GuidTable[0]);\r
831 } else {\r
832 GuidTable = (EFI_GUID *) (&mPcdDatabase->DxeDb.Init.GuidTable[0]);\r
833 }\r
80408db0 834 \r
835 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
836 \r
1fef733c 837 Guid = GuidTable + VariableHead->GuidTableIndex;\r
d0965169 838 Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
80408db0 839 VariableOffset = VariableHead->Offset;\r
80408db0 840 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);\r
6ac15f7c 841 \r
80408db0 842 if (EFI_NOT_FOUND == Status) {\r
6ac15f7c 843 if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
844 CopyMem (\r
845 StringTable + *(UINT16 *)(PcdDb + VariableHead->DefaultValueOffset),\r
846 Data,\r
847 *Size\r
848 );\r
849 } else {\r
850 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);\r
851 } \r
80408db0 852 Status = EFI_SUCCESS;\r
6ac15f7c 853 }\r
80408db0 854 break;\r
855 \r
856 case PCD_TYPE_DATA:\r
857 if (PtrType) {\r
858 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
859 CopyMem (InternalData, Data, *Size);\r
860 Status = EFI_SUCCESS;\r
861 } else {\r
862 Status = EFI_INVALID_PARAMETER;\r
863 }\r
864 break;\r
865 }\r
866\r
867 Status = EFI_SUCCESS;\r
868 switch (*Size) {\r
869 case sizeof(UINT8):\r
870 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
871 break;\r
872\r
873 case sizeof(UINT16):\r
874 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
875 break;\r
876\r
877 case sizeof(UINT32):\r
878 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
879 break;\r
880\r
881 case sizeof(UINT64):\r
882 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
883 break;\r
884\r
885 default:\r
886 ASSERT (FALSE);\r
887 Status = EFI_NOT_FOUND;\r
888 break;\r
889 }\r
890 break;\r
891\r
892 default:\r
893 ASSERT (FALSE);\r
894 Status = EFI_NOT_FOUND;\r
895 break;\r
896 }\r
897\r
898 EfiReleaseLock (&mPcdDatabaseLock);\r
899 \r
900 return Status;\r
901}\r
902\r
2ab6330e 903/**\r
904 Wrapper function for get PCD value for dynamic-ex PCD.\r
80408db0 905\r
2ab6330e 906 @param Guid Token space guid for dynamic-ex PCD.\r
3fd8027e 907 @param ExTokenNumber Token number for dynamic-ex PCD.\r
2ab6330e 908 @param GetSize The size of dynamic-ex PCD value.\r
80408db0 909\r
2ab6330e 910 @return PCD entry in PCD database.\r
80408db0 911\r
2ab6330e 912**/\r
80408db0 913VOID *\r
914ExGetWorker (\r
915 IN CONST EFI_GUID *Guid,\r
916 IN UINTN ExTokenNumber,\r
917 IN UINTN GetSize\r
918 ) \r
919{\r
920 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
921}\r
922\r
2ab6330e 923/**\r
924 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.\r
80408db0 925\r
2ab6330e 926 @param ExTokenNumber Token number for dynamic-ex PCD.\r
927 @param Guid Token space guid for dynamic-ex PCD.\r
928 @param Data Value want to be set.\r
929 @param SetSize The size of value.\r
80408db0 930\r
2ab6330e 931 @return status of ExSetWorker().\r
80408db0 932\r
2ab6330e 933**/\r
80408db0 934EFI_STATUS\r
935ExSetValueWorker (\r
936 IN UINTN ExTokenNumber,\r
937 IN CONST EFI_GUID *Guid,\r
938 IN VOID *Data,\r
939 IN UINTN SetSize\r
940 )\r
941{\r
942 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);\r
943}\r
944\r
2ab6330e 945/**\r
946 Set value for a dynamic PCD entry.\r
947 \r
948 This routine find the local token number according to dynamic-ex PCD's token \r
949 space guid and token number firstly, and invoke callback function if this PCD\r
950 entry registered callback function. Finally, invoken general SetWorker to set\r
951 PCD value.\r
952 \r
953 @param ExTokenNumber Dynamic-ex PCD token number.\r
954 @param Guid Token space guid for dynamic-ex PCD.\r
955 @param Data PCD value want to be set\r
956 @param SetSize Size of value.\r
957 @param PtrType If TRUE, this PCD entry is pointer type.\r
958 If FALSE, this PCD entry is not pointer type.\r
959\r
960 @return status of SetWorker().\r
80408db0 961\r
2ab6330e 962**/\r
80408db0 963EFI_STATUS\r
964ExSetWorker (\r
965 IN UINTN ExTokenNumber,\r
966 IN CONST EFI_GUID *Guid,\r
967 IN VOID *Data,\r
968 IN OUT UINTN *SetSize,\r
969 IN BOOLEAN PtrType\r
970 )\r
971{\r
972 UINTN TokenNumber;\r
973 \r
974 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
975\r
976 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
977\r
978 return SetWorker (TokenNumber, Data, SetSize, PtrType);\r
979\r
980}\r
981\r
2ab6330e 982/**\r
983 Set value for HII-type PCD.\r
80408db0 984\r
2ab6330e 985 A HII-type PCD's value is stored in a variable. Setting/Getting the value of \r
986 HII-type PCD is to visit this variable.\r
987 \r
988 @param VariableGuid Guid of variable which stored value of a HII-type PCD.\r
989 @param VariableName Unicode name of variable which stored value of a HII-type PCD.\r
990 @param Data Value want to be set.\r
991 @param DataSize Size of value\r
992 @param Offset Value offset of HII-type PCD in variable.\r
80408db0 993\r
2ab6330e 994 @return status of GetVariable()/SetVariable().\r
80408db0 995\r
2ab6330e 996**/\r
80408db0 997EFI_STATUS\r
998SetHiiVariable (\r
999 IN EFI_GUID *VariableGuid,\r
1000 IN UINT16 *VariableName,\r
1001 IN CONST VOID *Data,\r
1002 IN UINTN DataSize,\r
1003 IN UINTN Offset\r
1004 )\r
1005{\r
1006 UINTN Size;\r
1007 VOID *Buffer;\r
1008 EFI_STATUS Status;\r
1009 UINT32 Attribute;\r
b13151ff 1010 UINTN SetSize;\r
80408db0 1011\r
1012 Size = 0;\r
b13151ff 1013 SetSize = 0;\r
80408db0 1014\r
746be876 1015 //\r
1016 // Try to get original variable size information.\r
1017 //\r
80408db0 1018 Status = gRT->GetVariable (\r
1019 (UINT16 *)VariableName,\r
1020 VariableGuid,\r
1021 NULL,\r
1022 &Size,\r
1023 NULL\r
1024 );\r
b13151ff 1025 \r
80408db0 1026 if (Status == EFI_BUFFER_TOO_SMALL) {\r
746be876 1027 //\r
1028 // Patch new PCD's value to offset in given HII variable.\r
1029 //\r
b13151ff
LG
1030 if (Size >= (DataSize + Offset)) {\r
1031 SetSize = Size;\r
1032 } else {\r
1033 SetSize = DataSize + Offset;\r
1034 }\r
1035 Buffer = AllocatePool (SetSize);\r
80408db0 1036 ASSERT (Buffer != NULL);\r
1037\r
1038 Status = gRT->GetVariable (\r
1039 VariableName,\r
1040 VariableGuid,\r
1041 &Attribute,\r
1042 &Size,\r
1043 Buffer\r
1044 );\r
1045 \r
1046 ASSERT_EFI_ERROR (Status);\r
1047\r
1048 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
1049\r
1050 Status = gRT->SetVariable (\r
1051 VariableName,\r
1052 VariableGuid,\r
1053 Attribute,\r
b13151ff 1054 SetSize,\r
80408db0 1055 Buffer\r
1056 );\r
1057\r
1058 FreePool (Buffer);\r
1059 return Status;\r
746be876 1060 } else if (Status == EFI_NOT_FOUND) {\r
1061 //\r
1062 // If variable does not exist, a new variable need to be created.\r
1063 //\r
1064 \r
1065 Size = Offset + DataSize;\r
1066 \r
1067 Buffer = AllocateZeroPool (Size);\r
1068 ASSERT (Buffer != NULL);\r
1069 \r
1070 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
1071 \r
1072 Status = gRT->SetVariable (\r
1073 VariableName,\r
1074 VariableGuid,\r
1075 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1076 Size,\r
1077 Buffer\r
1078 );\r
1079\r
1080 FreePool (Buffer);\r
1081 return Status; \r
1082 }\r
80408db0 1083 \r
1084 //\r
746be876 1085 // If we drop to here, the value is failed to be written in to variable area\r
1086 // So, we will save the data in the PCD Database's volatile area.\r
80408db0 1087 //\r
1088 return Status;\r
1089}\r
1090\r
2ab6330e 1091/**\r
1092 Get local token number according to dynamic-ex PCD's {token space guid:token number}\r
80408db0 1093\r
2ab6330e 1094 A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
1095 in DEC file. PCD database maintain a mapping table that translate pair of {token\r
1096 space guid: token number} to local token number.\r
1097 \r
1098 @param Guid Token space guid for dynamic-ex PCD entry.\r
b9982883 1099 @param ExTokenNumber Dynamic-ex PCD token number.\r
80408db0 1100\r
2ab6330e 1101 @return local token number for dynamic-ex PCD.\r
80408db0 1102\r
2ab6330e 1103**/\r
80408db0 1104UINTN \r
1105GetExPcdTokenNumber (\r
1106 IN CONST EFI_GUID *Guid,\r
1107 IN UINT32 ExTokenNumber\r
1108 )\r
1109{\r
2ab6330e 1110 UINT32 Index;\r
80408db0 1111 DYNAMICEX_MAPPING *ExMap;\r
1112 EFI_GUID *GuidTable;\r
1113 EFI_GUID *MatchGuid;\r
1114 UINTN MatchGuidIdx;\r
1115\r
1116 if (!PEI_DATABASE_EMPTY) {\r
1117 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;\r
1118 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;\r
1119 \r
1120 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
1121 \r
1122 if (MatchGuid != NULL) {\r
1123\r
1124 MatchGuidIdx = MatchGuid - GuidTable;\r
1125 \r
2ab6330e 1126 for (Index = 0; Index < PEI_EXMAPPING_TABLE_SIZE; Index++) {\r
1127 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1128 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
1129 return ExMap[Index].LocalTokenNumber;\r
80408db0 1130 }\r
1131 }\r
1132 }\r
1133 }\r
1134 \r
1135 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;\r
1136 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;\r
1137\r
1138 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
1139 //\r
1140 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
1141 // error in the BUILD system.\r
1142 //\r
1143 ASSERT (MatchGuid != NULL);\r
1144\r
1145 MatchGuidIdx = MatchGuid - GuidTable;\r
1146 \r
2ab6330e 1147 for (Index = 0; Index < DXE_EXMAPPING_TABLE_SIZE; Index++) {\r
1148 if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
1149 (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
1150 return ExMap[Index].LocalTokenNumber;\r
80408db0 1151 }\r
1152 }\r
1153\r
1154 ASSERT (FALSE);\r
1155\r
1156 return 0;\r
1157}\r
1158\r
2ab6330e 1159/**\r
3fd8027e 1160 Get SKU ID table from PCD database.\r
2ab6330e 1161\r
1162 @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
1163 @param IsPeiPcd If TRUE, \r
80408db0 1164\r
2ab6330e 1165 @return Pointer to SKU ID array table\r
1166\r
1167**/\r
80408db0 1168SKU_ID *\r
1169GetSkuIdArray (\r
1170 IN UINTN LocalTokenNumberTableIdx,\r
1171 IN BOOLEAN IsPeiPcd\r
1172 )\r
1173{\r
1174 SKU_HEAD *SkuHead;\r
1175 UINTN LocalTokenNumber;\r
1176 UINT8 *Database;\r
1177\r
1178 if (IsPeiPcd) {\r
1179 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1180 Database = (UINT8 *) &mPcdDatabase->PeiDb;\r
1181 } else {\r
1182 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];\r
1183 Database = (UINT8 *) &mPcdDatabase->DxeDb;\r
1184 }\r
1185\r
1186 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
1187\r
1188 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
1189\r
1190 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
1191 \r
1192}\r
1193\r
2ab6330e 1194/**\r
3d53ba8b 1195 Wrapper function of getting index of PCD entry in size table.\r
1196 \r
2ab6330e 1197 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
2ab6330e 1198 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,\r
1199 If FALSE, the pcd entry is initialized in DXE phase.\r
1200\r
1201 @return index of PCD entry in size table.\r
2ab6330e 1202**/\r
80408db0 1203UINTN\r
3d53ba8b 1204GetSizeTableIndex (\r
1205 IN UINTN LocalTokenNumberTableIdx,\r
1206 IN BOOLEAN IsPeiDb\r
80408db0 1207 )\r
1208{\r
3d53ba8b 1209 UINT32 *LocalTokenNumberTable;\r
1210 UINTN LocalTokenNumber;\r
1211 UINTN Index;\r
1212 UINTN SizeTableIdx;\r
1213 SKU_ID *SkuIdTable;\r
80408db0 1214 \r
3d53ba8b 1215 if (IsPeiDb) {\r
1216 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1217 } else {\r
1218 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1219 }\r
1220\r
80408db0 1221 SizeTableIdx = 0;\r
1222\r
3d53ba8b 1223 for (Index = 0; Index < LocalTokenNumberTableIdx; Index ++) {\r
2ab6330e 1224 LocalTokenNumber = LocalTokenNumberTable[Index];\r
80408db0 1225\r
1226 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
1227 //\r
1228 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1229 // PCD entry.\r
1230 //\r
2ab6330e 1231 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1232 //\r
1233 // We have only one entry for VPD enabled PCD entry:\r
1234 // 1) MAX Size.\r
1235 // We consider current size is equal to MAX size.\r
1236 //\r
1237 SizeTableIdx++;\r
1238 } else {\r
1239 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1240 //\r
1241 // We have only two entry for Non-Sku enabled PCD entry:\r
1242 // 1) MAX SIZE\r
1243 // 2) Current Size\r
1244 //\r
1245 SizeTableIdx += 2;\r
1246 } else {\r
1247 //\r
1248 // We have these entry for SKU enabled PCD entry\r
1249 // 1) MAX SIZE\r
1250 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1251 //\r
2ab6330e 1252 SkuIdTable = GetSkuIdArray (Index, IsPeiDb);\r
80408db0 1253 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
1254 }\r
1255 }\r
1256 }\r
1257\r
1258 }\r
1259\r
3d53ba8b 1260 return SizeTableIdx; \r
80408db0 1261}\r
1262\r
2ab6330e 1263/**\r
1264 Get size of POINTER type PCD value.\r
1265\r
1266 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1267 @param MaxSize Maxmium size of POINTER type PCD value.\r
80408db0 1268\r
2ab6330e 1269 @return size of POINTER type PCD value.\r
80408db0 1270\r
2ab6330e 1271**/\r
80408db0 1272UINTN\r
1273GetPtrTypeSize (\r
1274 IN UINTN LocalTokenNumberTableIdx,\r
1275 OUT UINTN *MaxSize\r
1276 )\r
1277{\r
1278 INTN SizeTableIdx;\r
1279 UINTN LocalTokenNumber;\r
1280 SKU_ID *SkuIdTable;\r
1281 SIZE_INFO *SizeTable;\r
2ab6330e 1282 UINTN Index;\r
80408db0 1283 BOOLEAN IsPeiDb;\r
1284 UINT32 *LocalTokenNumberTable;\r
1285\r
1286 // EBC compiler is very choosy. It may report warning about comparison\r
1287 // between UINTN and 0 . So we add 1 in each size of the \r
1288 // comparison.\r
1289 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1290\r
1291\r
1292 if (IsPeiDb) {\r
1293 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1294 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1295 } else {\r
1296 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1297 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1298 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1299 }\r
1300\r
1301 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1302\r
1303 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1304 \r
1305 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1306\r
1307 *MaxSize = SizeTable[SizeTableIdx];\r
1308 //\r
1309 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1310 // PCD entry.\r
1311 //\r
2ab6330e 1312 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1313 //\r
1314 // We have only one entry for VPD enabled PCD entry:\r
1315 // 1) MAX Size.\r
1316 // We consider current size is equal to MAX size.\r
1317 //\r
1318 return *MaxSize;\r
1319 } else {\r
1320 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1321 //\r
1322 // We have only two entry for Non-Sku enabled PCD entry:\r
1323 // 1) MAX SIZE\r
1324 // 2) Current Size\r
1325 //\r
1326 return SizeTable[SizeTableIdx + 1];\r
1327 } else {\r
1328 //\r
1329 // We have these entry for SKU enabled PCD entry\r
1330 // 1) MAX SIZE\r
1331 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1332 //\r
1333 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1334 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
1335 if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1336 return SizeTable[SizeTableIdx + 1 + Index];\r
80408db0 1337 }\r
1338 }\r
1339 return SizeTable[SizeTableIdx + 1];\r
1340 }\r
1341 }\r
1342}\r
1343\r
2ab6330e 1344/**\r
3fd8027e 1345 Set size of POINTER type PCD value. The size should not exceed the maximum size\r
2ab6330e 1346 of this PCD value.\r
80408db0 1347\r
2ab6330e 1348 @param LocalTokenNumberTableIdx Index of local token number in local token number table.\r
1349 @param CurrentSize Size of POINTER type PCD value.\r
80408db0 1350\r
2ab6330e 1351 @retval TRUE Success to set size of PCD value.\r
1352 @retval FALSE Fail to set size of PCD value.\r
1353**/\r
80408db0 1354BOOLEAN\r
1355SetPtrTypeSize (\r
1356 IN UINTN LocalTokenNumberTableIdx,\r
1357 IN OUT UINTN *CurrentSize\r
1358 )\r
1359{\r
1360 INTN SizeTableIdx;\r
1361 UINTN LocalTokenNumber;\r
1362 SKU_ID *SkuIdTable;\r
1363 SIZE_INFO *SizeTable;\r
2ab6330e 1364 UINTN Index;\r
80408db0 1365 UINTN MaxSize;\r
1366 BOOLEAN IsPeiDb;\r
1367 UINT32 *LocalTokenNumberTable;\r
1368\r
2ab6330e 1369 //\r
80408db0 1370 // EBC compiler is very choosy. It may report warning about comparison\r
1371 // between UINTN and 0 . So we add 1 in each size of the \r
1372 // comparison.\r
2ab6330e 1373 //\r
80408db0 1374 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1375\r
1376 if (IsPeiDb) {\r
1377 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1378 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1379 } else {\r
1380 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1381 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1382 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1383 }\r
1384\r
1385 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1386\r
1387 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1388 \r
1389 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1390\r
1391 MaxSize = SizeTable[SizeTableIdx];\r
1392 //\r
1393 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1394 // PCD entry.\r
1395 //\r
2ab6330e 1396 if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
80408db0 1397 //\r
1398 // We shouldn't come here as we don't support SET for VPD\r
1399 //\r
1400 ASSERT (FALSE);\r
1401 return FALSE;\r
1402 } else {\r
1403 if ((*CurrentSize > MaxSize) ||\r
1404 (*CurrentSize == MAX_ADDRESS)) {\r
1405 *CurrentSize = MaxSize;\r
1406 return FALSE;\r
1407 } \r
1408 \r
1409 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1410 //\r
1411 // We have only two entry for Non-Sku enabled PCD entry:\r
1412 // 1) MAX SIZE\r
1413 // 2) Current Size\r
1414 //\r
1415 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1416 return TRUE;\r
1417 } else {\r
1418 //\r
1419 // We have these entry for SKU enabled PCD entry\r
1420 // 1) MAX SIZE\r
1421 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1422 //\r
1423 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
2ab6330e 1424 for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
1425 if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1426 SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;\r
80408db0 1427 return TRUE;\r
1428 }\r
1429 }\r
1430 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1431 return TRUE;\r
1432 }\r
1433 }\r
1434}\r