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