Refine some internal functions of PCD Driver.
[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 PCD_TOKEN_NUMBER 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 PCD_TOKEN_NUMBER 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 = PeiCoreLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, (VOID **) &VariablePpi);
148 ASSERT_EFI_ERROR (Status);
149
150 Size = 0;
151
152 Status = VariablePpi->PeiGetVariable (
153 GetPeiServicesTablePointer (),
154 VariableName,
155 (EFI_GUID *) VariableGuid,
156 NULL,
157 &Size,
158 NULL
159 );
160 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
161
162 Status = PeiCoreAllocatePool (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 }
180
181
182 UINT32
183 GetSkuEnabledTokenNumber (
184 UINT32 LocalTokenNumber,
185 UINTN Size
186 )
187 {
188 PEI_PCD_DATABASE *PeiPcdDb;
189 SKU_HEAD *SkuHead;
190 SKU_ID *SkuIdTable;
191 INTN i;
192 UINT8 *Value;
193
194 PeiPcdDb = GetPcdDatabase ();
195
196 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
197
198 SkuHead = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
199 Value = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));
200 SkuIdTable = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));
201
202 for (i = 0; i < SkuIdTable[0]; i++) {
203 if (PeiPcdDb->Init.SystemSkuId == SkuIdTable[i + 1]) {
204 break;
205 }
206 }
207
208 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {
209 case PCD_TYPE_VPD:
210 Value += sizeof(VPD_HEAD) * i;
211 return ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);
212
213 case PCD_TYPE_HII:
214 Value += sizeof(VARIABLE_HEAD) * i;
215 return ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);
216
217 case PCD_TYPE_DATA:
218 Value += Size * i;
219 return (Value - (UINT8 *) PeiPcdDb);
220
221 default:
222 ASSERT (FALSE);
223 }
224
225 ASSERT (FALSE);
226
227 return 0;
228
229 }
230
231
232
233
234 VOID
235 InvokeCallbackOnSet (
236 UINT32 ExTokenNumber,
237 CONST EFI_GUID *Guid, OPTIONAL
238 UINTN TokenNumber,
239 VOID *Data,
240 UINTN Size
241 )
242 {
243 EFI_HOB_GUID_TYPE *GuidHob;
244 PCD_PPI_CALLBACK *CallbackTable;
245 UINTN Idx;
246
247 if (Guid == NULL)
248 ASSERT (TokenNumber < PEI_LOCAL_TOKEN_NUMBER);
249
250 GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);
251 ASSERT (GuidHob != NULL);
252
253 CallbackTable = GET_GUID_HOB_DATA (GuidHob);
254
255 CallbackTable += (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));
256
257 for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
258 if (CallbackTable[Idx] != NULL) {
259 CallbackTable[Idx] (Guid,
260 (Guid == NULL)? TokenNumber: ExTokenNumber,
261 Data,
262 Size
263 );
264 }
265 }
266
267 }
268
269
270
271
272 EFI_STATUS
273 SetWorker (
274 PCD_TOKEN_NUMBER TokenNumber,
275 VOID *Data,
276 UINTN Size,
277 BOOLEAN PtrType
278 )
279 {
280 UINT32 LocalTokenNumber;
281 PEI_PCD_DATABASE *PeiPcdDb;
282 UINT16 StringTableIdx;
283 UINTN Offset;
284 VOID *InternalData;
285
286 ASSERT (TokenNumber < PEI_LOCAL_TOKEN_NUMBER);
287
288 PeiPcdDb = GetPcdDatabase ();
289
290 LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];
291
292 if (PtrType) {
293 ASSERT (PeiPcdDb->Init.SizeTable[TokenNumber] >= Size);
294 } else {
295 ASSERT (PeiPcdDb->Init.SizeTable[TokenNumber] == Size);
296 }
297
298 //
299 // We only invoke the callback function for Dynamic Type PCD Entry.
300 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
301 // type PCD entry in ExSetWorker.
302 //
303 if (TokenNumber < PEI_NEX_TOKEN_NUMBER) {
304 InvokeCallbackOnSet (0, NULL, TokenNumber, Data, Size);
305 }
306
307 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
308 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size);
309 }
310
311 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
312 InternalData = (VOID *) ((UINT8 *) PeiPcdDb + Offset);
313
314 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {
315 case PCD_TYPE_VPD:
316 case PCD_TYPE_HII:
317 {
318 ASSERT (FALSE);
319 return EFI_INVALID_PARAMETER;
320 }
321
322 case PCD_TYPE_STRING:
323 StringTableIdx = *((UINT16 *)InternalData);
324 CopyMem (&PeiPcdDb->Init.StringTable[StringTableIdx], Data, Size);
325 break;
326
327 case PCD_TYPE_DATA:
328 {
329
330 if (PtrType) {
331 CopyMem (InternalData, Data, Size);
332 return EFI_SUCCESS;
333 }
334
335 switch (Size) {
336 case sizeof(UINT8):
337 *((UINT8 *) InternalData) = *((UINT8 *) Data);
338 return EFI_SUCCESS;
339
340 case sizeof(UINT16):
341 *((UINT16 *) InternalData) = *((UINT16 *) Data);
342 return EFI_SUCCESS;
343
344 case sizeof(UINT32):
345 *((UINT32 *) InternalData) = *((UINT32 *) Data);
346 return EFI_SUCCESS;
347
348 case sizeof(UINT64):
349 *((UINT64 *) InternalData) = *((UINT64 *) Data);
350 return EFI_SUCCESS;
351
352 default:
353 ASSERT (FALSE);
354 return EFI_NOT_FOUND;
355 }
356 }
357
358 }
359
360 ASSERT (FALSE);
361 return EFI_NOT_FOUND;
362
363 }
364
365
366
367
368 EFI_STATUS
369 ExSetWorker (
370 IN PCD_TOKEN_NUMBER ExTokenNumber,
371 IN CONST EFI_GUID *Guid,
372 VOID *Data,
373 UINTN Size,
374 BOOLEAN PtrType
375 )
376 {
377 PCD_TOKEN_NUMBER TokenNumber;
378
379 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
380
381 InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, Size);
382
383 SetWorker (TokenNumber, Data, Size, PtrType);
384
385 return EFI_SUCCESS;
386
387 }
388
389
390
391
392 VOID *
393 ExGetWorker (
394 IN CONST EFI_GUID *Guid,
395 IN PCD_TOKEN_NUMBER ExTokenNumber,
396 IN UINTN GetSize
397 )
398 {
399 return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);
400 }
401
402
403
404
405 VOID *
406 GetWorker (
407 PCD_TOKEN_NUMBER TokenNumber,
408 UINTN GetSize
409 )
410 {
411 UINT32 Offset;
412 EFI_GUID *Guid;
413 UINT16 *Name;
414 VARIABLE_HEAD *VariableHead;
415 EFI_STATUS Status;
416 UINTN DataSize;
417 VOID *Data;
418 UINT16 *StringTable;
419 UINT16 StringTableIdx;
420 PEI_PCD_DATABASE *PeiPcdDb;
421 UINT32 LocalTokenNumber;
422 UINTN Size;
423
424 ASSERT (TokenNumber < PEI_LOCAL_TOKEN_NUMBER);
425
426 Size = PeiPcdGetSize(TokenNumber);
427
428 ASSERT (GetSize == Size || GetSize == 0);
429
430 PeiPcdDb = GetPcdDatabase ();
431
432 LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];
433
434 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
435 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size);
436 }
437
438 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
439 StringTable = PeiPcdDb->Init.StringTable;
440
441 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {
442 case PCD_TYPE_VPD:
443 {
444 VPD_HEAD *VpdHead;
445 VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
446 return (VOID *) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
447 }
448
449 case PCD_TYPE_HII:
450 {
451 VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
452
453 Guid = &(PeiPcdDb->Init.GuidTable[VariableHead->GuidTableIndex]);
454 Name = &StringTable[VariableHead->StringIndex];
455
456 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
457 ASSERT_EFI_ERROR (Status);
458 ASSERT (DataSize >= (UINTN) (VariableHead->Offset + Size));
459
460 return (VOID *) ((UINT8 *) Data + VariableHead->Offset);
461 }
462
463 case PCD_TYPE_DATA:
464 return (VOID *) ((UINT8 *)PeiPcdDb + Offset);
465 break;
466
467 case PCD_TYPE_STRING:
468 StringTableIdx = (UINT16) *((UINT8 *) PeiPcdDb + Offset);
469 return (VOID *) (&StringTable[StringTableIdx]);
470
471 default:
472 ASSERT (FALSE);
473 break;
474
475 }
476
477 ASSERT (FALSE);
478
479 return NULL;
480
481 }
482
483
484 PCD_TOKEN_NUMBER
485 GetExPcdTokenNumber (
486 IN CONST EFI_GUID *Guid,
487 IN UINT32 ExTokenNumber
488 )
489 {
490 UINT32 i;
491 DYNAMICEX_MAPPING *ExMap;
492 EFI_GUID *GuidTable;
493 EFI_GUID *MatchGuid;
494 UINTN MatchGuidIdx;
495 PEI_PCD_DATABASE *PeiPcdDb;
496
497 PeiPcdDb = GetPcdDatabase();
498
499 ExMap = PeiPcdDb->Init.ExMapTable;
500 GuidTable = PeiPcdDb->Init.GuidTable;
501
502 MatchGuid = ScanGuid (GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);
503 ASSERT (MatchGuid != NULL);
504
505 MatchGuidIdx = MatchGuid - GuidTable;
506
507 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
508 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
509 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
510 return ExMap[i].LocalTokenNumber;
511 }
512 }
513
514 ASSERT (FALSE);
515
516 return 0;
517 }
518
519
520
521 PEI_PCD_DATABASE *
522 GetPcdDatabase (
523 VOID
524 )
525 {
526 EFI_HOB_GUID_TYPE *GuidHob;
527
528 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
529 ASSERT (GuidHob != NULL);
530
531 return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
532 }
533