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