]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EdkModulePkg/Universal/PCD/Pei/Service.c
Add in support for GetNextTokenNumber API.
[mirror_edk2.git] / EdkModulePkg / Universal / PCD / Pei / Service.c
... / ...
CommitLineData
1/** @file\r
2Private functions used by PCD PEIM.\r
3\r
4Copyright (c) 2006, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13\r
14Module Name: Service.c\r
15\r
16**/\r
17#include "Service.h"\r
18\r
19\r
20/**\r
21 The function registers the CallBackOnSet fucntion\r
22 according to TokenNumber and EFI_GUID space.\r
23\r
24 @param[in] TokenNumber The token number.\r
25 @param[in] Guid The GUID space.\r
26 @param[in] CallBackFunction The Callback function to be registered.\r
27\r
28 @retval EFI_SUCCESS If the Callback function is registered.\r
29 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.\r
30--*/\r
31EFI_STATUS\r
32PeiRegisterCallBackWorker (\r
33 IN UINTN ExTokenNumber,\r
34 IN CONST EFI_GUID *Guid, OPTIONAL\r
35 IN PCD_PPI_CALLBACK CallBackFunction,\r
36 IN BOOLEAN Register\r
37)\r
38{\r
39 EFI_HOB_GUID_TYPE *GuidHob;\r
40 PCD_PPI_CALLBACK *CallbackTable;\r
41 PCD_PPI_CALLBACK Compare;\r
42 PCD_PPI_CALLBACK Assign;\r
43 UINT32 LocalTokenNumber;\r
44 UINTN TokenNumber;\r
45 UINTN Idx;\r
46 EX_PCD_ENTRY_ATTRIBUTE Attr;\r
47\r
48 if (Guid == NULL) {\r
49 TokenNumber = ExTokenNumber;\r
50 ASSERT (TokenNumber < PEI_NEX_TOKEN_NUMBER);\r
51 LocalTokenNumber = GetPcdDatabase()->Init.LocalTokenNumberTable[TokenNumber];\r
52 } else {\r
53 GetExPcdTokenAttributes (Guid, ExTokenNumber, &Attr);\r
54 TokenNumber = Attr.TokenNumber;\r
55 LocalTokenNumber = Attr.LocalTokenNumberAlias;\r
56 }\r
57\r
58 ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);\r
59 ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);\r
60\r
61 GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
62 ASSERT (GuidHob != NULL);\r
63 \r
64 CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
65 CallbackTable = CallbackTable + (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
66\r
67 Compare = Register? NULL: CallBackFunction;\r
68 Assign = Register? CallBackFunction: NULL;\r
69\r
70\r
71 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
72 if (CallbackTable[Idx] == Compare) {\r
73 CallbackTable[Idx] = Assign;\r
74 return EFI_SUCCESS;\r
75 }\r
76 }\r
77\r
78 return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND;\r
79\r
80}\r
81\r
82\r
83\r
84\r
85/**\r
86 The function builds the PCD database based on the\r
87 PCD_IMAGE on the flash.\r
88\r
89 @param[in] PcdImageOnFlash The PCD image on flash.\r
90\r
91 @retval VOID\r
92--*/\r
93VOID\r
94BuildPcdDatabase (\r
95 VOID\r
96 )\r
97{\r
98 PEI_PCD_DATABASE *Database;\r
99 VOID *CallbackFnTable;\r
100 UINTN SizeOfCallbackFnTable;\r
101 \r
102 Database = BuildGuidHob (&gPcdDataBaseHobGuid, sizeof (PEI_PCD_DATABASE));\r
103\r
104 ZeroMem (Database, sizeof (PEI_PCD_DATABASE));\r
105\r
106 //\r
107 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE\r
108 //\r
109 \r
110 CopyMem (&Database->Init, &gPEIPcdDbInit, sizeof (gPEIPcdDbInit));\r
111\r
112 SizeOfCallbackFnTable = PEI_LOCAL_TOKEN_NUMBER * sizeof (PCD_PPI_CALLBACK) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry);\r
113\r
114 CallbackFnTable = BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid, SizeOfCallbackFnTable);\r
115 \r
116 ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);\r
117 \r
118 return;\r
119}\r
120\r
121\r
122\r
123/**\r
124 The function is provided by PCD PEIM and PCD DXE driver to\r
125 do the work of reading a HII variable from variable service.\r
126\r
127 @param[in] VariableGuid The Variable GUID.\r
128 @param[in] VariableName The Variable Name.\r
129 @param[out] VariableData The output data.\r
130 @param[out] VariableSize The size of the variable.\r
131\r
132 @retval EFI_SUCCESS Operation successful.\r
133 @retval EFI_SUCCESS Variablel not found.\r
134--*/\r
135EFI_STATUS\r
136GetHiiVariable (\r
137 IN CONST EFI_GUID *VariableGuid,\r
138 IN UINT16 *VariableName,\r
139 OUT VOID **VariableData,\r
140 OUT UINTN *VariableSize\r
141 )\r
142{\r
143 UINTN Size;\r
144 EFI_STATUS Status;\r
145 VOID *Buffer;\r
146 EFI_PEI_READ_ONLY_VARIABLE_PPI *VariablePpi;\r
147\r
148 Status = PeiCoreLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, (VOID **) &VariablePpi);\r
149 ASSERT_EFI_ERROR (Status);\r
150\r
151 Size = 0;\r
152\r
153 Status = VariablePpi->PeiGetVariable (\r
154 GetPeiServicesTablePointer (),\r
155 VariableName,\r
156 (EFI_GUID *) VariableGuid,\r
157 NULL,\r
158 &Size,\r
159 NULL\r
160 );\r
161 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
162\r
163 Status = PeiCoreAllocatePool (Size, &Buffer);\r
164 ASSERT_EFI_ERROR (Status);\r
165\r
166 Status = VariablePpi->PeiGetVariable (\r
167 GetPeiServicesTablePointer (),\r
168 (UINT16 *) VariableName,\r
169 (EFI_GUID *) VariableGuid,\r
170 NULL,\r
171 &Size,\r
172 Buffer\r
173 );\r
174 ASSERT_EFI_ERROR (Status);\r
175\r
176 *VariableSize = Size;\r
177 *VariableData = Buffer;\r
178\r
179 return EFI_SUCCESS;\r
180}\r
181\r
182\r
183UINT32\r
184GetSkuEnabledTokenNumber (\r
185 UINT32 LocalTokenNumber,\r
186 UINTN Size\r
187 ) \r
188{\r
189 PEI_PCD_DATABASE *PeiPcdDb;\r
190 SKU_HEAD *SkuHead;\r
191 SKU_ID *SkuIdTable;\r
192 INTN i;\r
193 UINT8 *Value;\r
194\r
195 PeiPcdDb = GetPcdDatabase ();\r
196\r
197 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
198\r
199 SkuHead = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
200 Value = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));\r
201 SkuIdTable = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));\r
202 \r
203 for (i = 0; i < SkuIdTable[0]; i++) {\r
204 if (PeiPcdDb->Init.SystemSkuId == SkuIdTable[i + 1]) {\r
205 break;\r
206 }\r
207 }\r
208\r
209 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
210 case PCD_TYPE_VPD:\r
211 Value += sizeof(VPD_HEAD) * i;\r
212 return ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);\r
213\r
214 case PCD_TYPE_HII:\r
215 Value += sizeof(VARIABLE_HEAD) * i;\r
216 return ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);\r
217 \r
218 case PCD_TYPE_DATA:\r
219 Value += Size * i;\r
220 return (Value - (UINT8 *) PeiPcdDb);\r
221 \r
222 default:\r
223 ASSERT (FALSE);\r
224 }\r
225\r
226 ASSERT (FALSE);\r
227\r
228 return 0;\r
229 \r
230}\r
231\r
232\r
233\r
234\r
235VOID\r
236InvokeCallbackOnSet (\r
237 UINT32 ExTokenNumber,\r
238 CONST EFI_GUID *Guid, OPTIONAL\r
239 UINTN TokenNumber,\r
240 VOID *Data,\r
241 UINTN Size\r
242 )\r
243{\r
244 EFI_HOB_GUID_TYPE *GuidHob;\r
245 PCD_PPI_CALLBACK *CallbackTable;\r
246 UINTN Idx;\r
247\r
248 if (Guid == NULL)\r
249 ASSERT (TokenNumber < PEI_LOCAL_TOKEN_NUMBER);\r
250\r
251 GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
252 ASSERT (GuidHob != NULL);\r
253 \r
254 CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
255\r
256 CallbackTable += (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
257\r
258 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
259 if (CallbackTable[Idx] != NULL) {\r
260 CallbackTable[Idx] (Guid,\r
261 (Guid == NULL)? TokenNumber: ExTokenNumber,\r
262 Data,\r
263 Size\r
264 );\r
265 }\r
266 }\r
267 \r
268}\r
269\r
270EFI_STATUS\r
271SetWorker (\r
272 UINTN TokenNumber,\r
273 VOID *Data,\r
274 UINTN Size,\r
275 BOOLEAN PtrType\r
276 )\r
277{\r
278 UINT32 LocalTokenNumber;\r
279 PEI_PCD_DATABASE *PeiPcdDb;\r
280\r
281 ASSERT (TokenNumber < PEI_LOCAL_TOKEN_NUMBER);\r
282 \r
283 PeiPcdDb = GetPcdDatabase ();\r
284\r
285 LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];\r
286\r
287 if (PtrType) {\r
288 ASSERT (PeiPcdDb->Init.SizeTable[TokenNumber] >= Size);\r
289 } else {\r
290 ASSERT (PeiPcdDb->Init.SizeTable[TokenNumber] == Size);\r
291 }\r
292\r
293 InvokeCallbackOnSet (0, NULL, TokenNumber, Data, Size);\r
294\r
295 return SetWorkerByLocalTokenNumber (LocalTokenNumber, Data, Size, PtrType);\r
296\r
297}\r
298\r
299\r
300\r
301\r
302EFI_STATUS\r
303ExSetWorker (\r
304 IN UINT32 ExTokenNumber,\r
305 IN CONST EFI_GUID *Guid,\r
306 VOID *Data,\r
307 UINTN Size,\r
308 BOOLEAN PtrType\r
309 )\r
310{\r
311 PEI_PCD_DATABASE *PeiPcdDb;\r
312 EX_PCD_ENTRY_ATTRIBUTE Attr;\r
313\r
314\r
315 PeiPcdDb = GetPcdDatabase ();\r
316\r
317 GetExPcdTokenAttributes (Guid, ExTokenNumber, &Attr);\r
318\r
319 ASSERT (!PtrType && Attr.Size);\r
320\r
321 ASSERT (PtrType && Attr.Size >= Size);\r
322\r
323 InvokeCallbackOnSet (ExTokenNumber, Guid, Attr.TokenNumber, Data, Size);\r
324\r
325 SetWorkerByLocalTokenNumber (Attr.LocalTokenNumberAlias, Data, Size, PtrType);\r
326\r
327 return EFI_SUCCESS;\r
328 \r
329}\r
330\r
331\r
332\r
333\r
334EFI_STATUS\r
335SetWorkerByLocalTokenNumber (\r
336 UINT32 LocalTokenNumber,\r
337 VOID *Data,\r
338 UINTN Size,\r
339 BOOLEAN PtrType\r
340 )\r
341{\r
342 PEI_PCD_DATABASE *PeiPcdDb;\r
343 UINT8 *PeiPcdDbRaw;\r
344 UINT16 StringTableIdx;\r
345 UINTN Offset;\r
346 VOID *InternalData;\r
347 \r
348\r
349 PeiPcdDb = GetPcdDatabase ();\r
350 PeiPcdDbRaw = (UINT8 *) PeiPcdDb;\r
351 \r
352 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
353 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size);\r
354 }\r
355\r
356 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
357 InternalData = (VOID *) (PeiPcdDbRaw + Offset);\r
358 \r
359 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
360 case PCD_TYPE_VPD:\r
361 case PCD_TYPE_HII:\r
362 {\r
363 ASSERT (FALSE);\r
364 return EFI_INVALID_PARAMETER;\r
365 }\r
366\r
367 case PCD_TYPE_STRING:\r
368 StringTableIdx = *((UINT16 *)InternalData);\r
369 CopyMem (&PeiPcdDb->Init.StringTable[StringTableIdx], Data, Size);\r
370 break;\r
371\r
372 case PCD_TYPE_DATA:\r
373 {\r
374 \r
375 if (PtrType) {\r
376 CopyMem (InternalData, Data, Size);\r
377 return EFI_SUCCESS;\r
378 }\r
379\r
380 switch (Size) {\r
381 case sizeof(UINT8):\r
382 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
383 return EFI_SUCCESS;\r
384\r
385 case sizeof(UINT16):\r
386 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
387 return EFI_SUCCESS;\r
388\r
389 case sizeof(UINT32):\r
390 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
391 return EFI_SUCCESS;\r
392\r
393 case sizeof(UINT64):\r
394 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
395 return EFI_SUCCESS;\r
396\r
397 default:\r
398 ASSERT (FALSE);\r
399 return EFI_NOT_FOUND;\r
400 }\r
401 }\r
402 \r
403 }\r
404\r
405 ASSERT (FALSE);\r
406 return EFI_NOT_FOUND;\r
407}\r
408\r
409\r
410VOID *\r
411GetWorkerByLocalTokenNumber (\r
412 PEI_PCD_DATABASE *PeiPcdDb,\r
413 UINT32 LocalTokenNumber,\r
414 UINTN Size\r
415 )\r
416{\r
417 UINT32 Offset;\r
418 EFI_GUID *Guid;\r
419 UINT16 *Name;\r
420 VARIABLE_HEAD *VariableHead;\r
421 EFI_STATUS Status;\r
422 UINTN DataSize;\r
423 VOID *Data;\r
424 UINT16 *StringTable;\r
425 UINT16 StringTableIdx;\r
426 \r
427 PeiPcdDb = GetPcdDatabase ();\r
428\r
429 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
430 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size);\r
431 }\r
432\r
433 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
434 StringTable = PeiPcdDb->Init.StringTable;\r
435 \r
436 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
437 case PCD_TYPE_VPD:\r
438 {\r
439 VPD_HEAD *VpdHead;\r
440 VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
441 return (VOID *) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);\r
442 }\r
443 \r
444 case PCD_TYPE_HII:\r
445 {\r
446 VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
447 \r
448 Guid = &(PeiPcdDb->Init.GuidTable[VariableHead->GuidTableIndex]);\r
449 Name = &StringTable[VariableHead->StringIndex];\r
450\r
451 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
452 ASSERT_EFI_ERROR (Status);\r
453 ASSERT (DataSize >= (UINTN) (VariableHead->Offset + Size));\r
454\r
455 return (VOID *) ((UINT8 *) Data + VariableHead->Offset);\r
456 }\r
457\r
458 case PCD_TYPE_DATA:\r
459 return (VOID *) ((UINT8 *)PeiPcdDb + Offset);\r
460 break;\r
461\r
462 case PCD_TYPE_STRING:\r
463 StringTableIdx = (UINT16) *((UINT8 *) PeiPcdDb + Offset);\r
464 return (VOID *) (&StringTable[StringTableIdx]);\r
465\r
466 default:\r
467 ASSERT (FALSE);\r
468 break;\r
469 \r
470 }\r
471\r
472 ASSERT (FALSE);\r
473 \r
474 return NULL;\r
475 \r
476}\r
477\r
478\r
479VOID *\r
480ExGetWorker (\r
481 IN CONST EFI_GUID *Guid,\r
482 IN UINT32 ExTokenNumber,\r
483 IN UINTN GetSize\r
484 )\r
485{\r
486 EX_PCD_ENTRY_ATTRIBUTE Attr;\r
487\r
488 GetExPcdTokenAttributes (Guid, ExTokenNumber, &Attr);\r
489 \r
490 ASSERT ((GetSize == Attr.Size) || (GetSize == 0));\r
491\r
492 return GetWorkerByLocalTokenNumber (GetPcdDatabase(),\r
493 Attr.LocalTokenNumberAlias,\r
494 Attr.Size\r
495 );\r
496}\r
497\r
498VOID *\r
499GetWorker (\r
500 UINTN TokenNumber,\r
501 UINTN GetSize\r
502 )\r
503{\r
504 PEI_PCD_DATABASE *PeiPcdDb;\r
505\r
506 ASSERT (TokenNumber < PEI_LOCAL_TOKEN_NUMBER);\r
507\r
508 ASSERT (GetSize == PeiPcdGetSize (TokenNumber) || GetSize == 0);\r
509\r
510 PeiPcdDb = GetPcdDatabase ();\r
511 \r
512 return GetWorkerByLocalTokenNumber (PeiPcdDb, PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber], GetSize);\r
513}\r
514\r
515\r
516VOID\r
517GetExPcdTokenAttributes (\r
518 IN CONST EFI_GUID *Guid,\r
519 IN UINT32 ExTokenNumber,\r
520 OUT EX_PCD_ENTRY_ATTRIBUTE *ExAttr\r
521 )\r
522{\r
523 UINT32 i;\r
524 DYNAMICEX_MAPPING *ExMap;\r
525 EFI_GUID *GuidTable;\r
526 PEI_PCD_DATABASE *PeiPcdDb;\r
527\r
528 PeiPcdDb = GetPcdDatabase();\r
529 \r
530 ExMap = PeiPcdDb->Init.ExMapTable;\r
531 GuidTable = PeiPcdDb->Init.GuidTable;\r
532 \r
533 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
534 if ((ExTokenNumber == ExMap[i].ExTokenNumber) && \r
535 CompareGuid (Guid, (CONST EFI_GUID *) &GuidTable[ExMap[i].ExGuidIndex])) {\r
536 ExAttr->TokenNumber = i + PEI_NEX_TOKEN_NUMBER;\r
537 ExAttr->Size = PeiPcdDb->Init.SizeTable[i + PEI_NEX_TOKEN_NUMBER];\r
538 ExAttr->LocalTokenNumberAlias = ExMap[i].LocalTokenNumber;\r
539 }\r
540 }\r
541 \r
542 ASSERT (FALSE);\r
543 \r
544 return;\r
545}\r
546\r
547\r
548\r
549PEI_PCD_DATABASE *\r
550GetPcdDatabase (\r
551 VOID\r
552 )\r
553{\r
554 EFI_HOB_GUID_TYPE *GuidHob;\r
555\r
556 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
557 ASSERT (GuidHob != NULL);\r
558 \r
559 return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
560}\r
561\r