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