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