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