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