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