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