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