Import PCD dxe and PCD pei modules.
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Pcd.c
1 /** @file
2 PCD DXE driver
3
4 Copyright (c) 2006 - 2007, 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: Pcd.c
15
16 **/
17
18 //
19 // Include common header file for this module.
20 //
21 #include "CommonHeader.h"
22
23 #include "Service.h"
24
25 EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_CALLBACK);
26
27 PCD_PROTOCOL mPcdInstance = {
28 DxePcdSetSku,
29
30 DxePcdGet8,
31 DxePcdGet16,
32 DxePcdGet32,
33 DxePcdGet64,
34 DxePcdGetPtr,
35 DxePcdGetBool,
36 DxePcdGetSize,
37
38 DxePcdGet8Ex,
39 DxePcdGet16Ex,
40 DxePcdGet32Ex,
41 DxePcdGet64Ex,
42 DxePcdGetPtrEx,
43 DxePcdGetBoolEx,
44 DxePcdGetSizeEx,
45
46 DxePcdSet8,
47 DxePcdSet16,
48 DxePcdSet32,
49 DxePcdSet64,
50 DxePcdSetPtr,
51 DxePcdSetBool,
52
53 DxePcdSet8Ex,
54 DxePcdSet16Ex,
55 DxePcdSet32Ex,
56 DxePcdSet64Ex,
57 DxePcdSetPtrEx,
58 DxePcdSetBoolEx,
59
60 DxeRegisterCallBackOnSet,
61 DxeUnRegisterCallBackOnSet,
62 DxePcdGetNextToken,
63 DxePcdGetNextTokenSpace
64 };
65
66
67 //
68 // Static global to reduce the code size
69 //
70 static EFI_HANDLE mNewHandle = NULL;
71
72 EFI_STATUS
73 EFIAPI
74 PcdDxeInit (
75 IN EFI_HANDLE ImageHandle,
76 IN EFI_SYSTEM_TABLE *SystemTable
77 )
78 {
79 EFI_STATUS Status;
80
81 //
82 // Make sure the Pcd Protocol is not already installed in the system
83 //
84
85 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);
86
87 BuildPcdDxeDataBase ();
88
89 Status = gBS->InstallProtocolInterface (
90 &mNewHandle,
91 &gPcdProtocolGuid,
92 EFI_NATIVE_INTERFACE,
93 &mPcdInstance
94 );
95
96 ASSERT_EFI_ERROR (Status);
97
98 return EFI_SUCCESS;
99
100 }
101
102
103 VOID
104 EFIAPI
105 DxePcdSetSku (
106 IN UINTN SkuId
107 )
108 {
109 mPcdDatabase->PeiDb.Init.SystemSkuId = (SKU_ID) SkuId;
110
111 return;
112 }
113
114
115
116 UINT8
117 EFIAPI
118 DxePcdGet8 (
119 IN UINTN TokenNumber
120 )
121 {
122 return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));
123 }
124
125
126
127 UINT16
128 EFIAPI
129 DxePcdGet16 (
130 IN UINTN TokenNumber
131 )
132 {
133 return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
134 }
135
136
137
138 UINT32
139 EFIAPI
140 DxePcdGet32 (
141 IN UINTN TokenNumber
142 )
143 {
144 return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
145 }
146
147
148
149 UINT64
150 EFIAPI
151 DxePcdGet64 (
152 IN UINTN TokenNumber
153 )
154 {
155 return ReadUnaligned64(GetWorker (TokenNumber, sizeof (UINT64)));
156 }
157
158
159
160 VOID *
161 EFIAPI
162 DxePcdGetPtr (
163 IN UINTN TokenNumber
164 )
165 {
166 return GetWorker (TokenNumber, 0);
167 }
168
169
170
171 BOOLEAN
172 EFIAPI
173 DxePcdGetBool (
174 IN UINTN TokenNumber
175 )
176 {
177 return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));
178 }
179
180
181
182 UINTN
183 EFIAPI
184 DxePcdGetSize (
185 IN UINTN TokenNumber
186 )
187 {
188 UINTN Size;
189 UINT32 *LocalTokenNumberTable;
190 BOOLEAN IsPeiDb;
191 UINTN MaxSize;
192 UINTN TmpTokenNumber;
193 //
194 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
195 // We have to decrement TokenNumber by 1 to make it usable
196 // as the array index.
197 //
198 TokenNumber--;
199
200 //
201 // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber
202 //
203 TmpTokenNumber = TokenNumber;
204
205 // EBC compiler is very choosy. It may report warning about comparison
206 // between UINTN and 0 . So we add 1 in each size of the
207 // comparison.
208 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);
209
210 // EBC compiler is very choosy. It may report warning about comparison
211 // between UINTN and 0 . So we add 1 in each size of the
212 // comparison.
213 IsPeiDb = (BOOLEAN) (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
214
215 TokenNumber = IsPeiDb ? TokenNumber :
216 (TokenNumber - PEI_LOCAL_TOKEN_NUMBER);
217
218 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable
219 : mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
220
221 Size = (LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
222
223 if (Size == 0) {
224 //
225 // For pointer type, we need to scan the SIZE_TABLE to get the current size.
226 //
227 return GetPtrTypeSize (TmpTokenNumber, &MaxSize);
228 } else {
229 return Size;
230 }
231
232 }
233
234
235
236 UINT8
237 EFIAPI
238 DxePcdGet8Ex (
239 IN CONST EFI_GUID *Guid,
240 IN UINTN ExTokenNumber
241 )
242 {
243 return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof(UINT8)));
244 }
245
246
247
248 UINT16
249 EFIAPI
250 DxePcdGet16Ex (
251 IN CONST EFI_GUID *Guid,
252 IN UINTN ExTokenNumber
253 )
254 {
255 return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT16)));
256 }
257
258
259
260 UINT32
261 EFIAPI
262 DxePcdGet32Ex (
263 IN CONST EFI_GUID *Guid,
264 IN UINTN ExTokenNumber
265 )
266 {
267 return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT32)));
268 }
269
270
271
272 UINT64
273 EFIAPI
274 DxePcdGet64Ex (
275 IN CONST EFI_GUID *Guid,
276 IN UINTN ExTokenNumber
277 )
278 {
279 return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT64)));
280 }
281
282
283
284 VOID *
285 EFIAPI
286 DxePcdGetPtrEx (
287 IN CONST EFI_GUID *Guid,
288 IN UINTN ExTokenNumber
289 )
290 {
291 return ExGetWorker (Guid, ExTokenNumber, 0);
292 }
293
294
295
296 BOOLEAN
297 EFIAPI
298 DxePcdGetBoolEx (
299 IN CONST EFI_GUID *Guid,
300 IN UINTN ExTokenNumber
301 )
302 {
303 return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof(BOOLEAN)));
304 }
305
306
307
308 UINTN
309 EFIAPI
310 DxePcdGetSizeEx (
311 IN CONST EFI_GUID *Guid,
312 IN UINTN ExTokenNumber
313 )
314 {
315 return DxePcdGetSize(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber));
316 }
317
318
319
320 EFI_STATUS
321 EFIAPI
322 DxePcdSet8 (
323 IN UINTN TokenNumber,
324 IN UINT8 Value
325 )
326 {
327 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
328 }
329
330
331
332 EFI_STATUS
333 EFIAPI
334 DxePcdSet16 (
335 IN UINTN TokenNumber,
336 IN UINT16 Value
337 )
338 {
339 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
340 }
341
342
343
344 EFI_STATUS
345 EFIAPI
346 DxePcdSet32 (
347 IN UINTN TokenNumber,
348 IN UINT32 Value
349 )
350 {
351 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
352 }
353
354
355
356 EFI_STATUS
357 EFIAPI
358 DxePcdSet64 (
359 IN UINTN TokenNumber,
360 IN UINT64 Value
361 )
362 {
363 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
364 }
365
366
367
368 EFI_STATUS
369 EFIAPI
370 DxePcdSetPtr (
371 IN UINTN TokenNumber,
372 IN OUT UINTN *SizeOfBuffer,
373 IN VOID *Buffer
374 )
375 {
376 return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
377 }
378
379
380
381 EFI_STATUS
382 EFIAPI
383 DxePcdSetBool (
384 IN UINTN TokenNumber,
385 IN BOOLEAN Value
386 )
387 {
388 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
389 }
390
391
392
393 EFI_STATUS
394 EFIAPI
395 DxePcdSet8Ex (
396 IN CONST EFI_GUID *Guid,
397 IN UINTN ExTokenNumber,
398 IN UINT8 Value
399 )
400 {
401 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
402 }
403
404
405
406 EFI_STATUS
407 EFIAPI
408 DxePcdSet16Ex (
409 IN CONST EFI_GUID *Guid,
410 IN UINTN ExTokenNumber,
411 IN UINT16 Value
412 )
413 {
414 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
415 }
416
417
418
419 EFI_STATUS
420 EFIAPI
421 DxePcdSet32Ex (
422 IN CONST EFI_GUID *Guid,
423 IN UINTN ExTokenNumber,
424 IN UINT32 Value
425 )
426 {
427 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
428 }
429
430
431
432 EFI_STATUS
433 EFIAPI
434 DxePcdSet64Ex (
435 IN CONST EFI_GUID *Guid,
436 IN UINTN ExTokenNumber,
437 IN UINT64 Value
438 )
439 {
440 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
441 }
442
443
444
445 EFI_STATUS
446 EFIAPI
447 DxePcdSetPtrEx (
448 IN CONST EFI_GUID *Guid,
449 IN UINTN ExTokenNumber,
450 IN OUT UINTN *SizeOfBuffer,
451 IN VOID *Buffer
452 )
453 {
454 return ExSetWorker(ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);
455 }
456
457
458
459 EFI_STATUS
460 EFIAPI
461 DxePcdSetBoolEx (
462 IN CONST EFI_GUID *Guid,
463 IN UINTN ExTokenNumber,
464 IN BOOLEAN Value
465 )
466 {
467 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
468 }
469
470
471
472
473 EFI_STATUS
474 EFIAPI
475 DxeRegisterCallBackOnSet (
476 IN CONST EFI_GUID *Guid, OPTIONAL
477 IN UINTN TokenNumber,
478 IN PCD_PROTOCOL_CALLBACK CallBackFunction
479 )
480 {
481 EFI_STATUS Status;
482
483 ASSERT (CallBackFunction != NULL);
484
485 //
486 // Aquire lock to prevent reentrance from TPL_CALLBACK level
487 //
488 EfiAcquireLock (&mPcdDatabaseLock);
489
490 Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
491
492 EfiReleaseLock (&mPcdDatabaseLock);
493
494 return Status;
495 }
496
497
498
499 EFI_STATUS
500 EFIAPI
501 DxeUnRegisterCallBackOnSet (
502 IN CONST EFI_GUID *Guid, OPTIONAL
503 IN UINTN TokenNumber,
504 IN PCD_PROTOCOL_CALLBACK CallBackFunction
505 )
506 {
507 EFI_STATUS Status;
508
509 ASSERT (CallBackFunction != NULL);
510
511 //
512 // Aquire lock to prevent reentrance from TPL_CALLBACK level
513 //
514 EfiAcquireLock (&mPcdDatabaseLock);
515
516 Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
517
518 EfiReleaseLock (&mPcdDatabaseLock);
519
520 return Status;
521 }
522
523
524
525 EFI_STATUS
526 EFIAPI
527 DxePcdGetNextToken (
528 IN CONST EFI_GUID *Guid, OPTIONAL
529 IN OUT UINTN *TokenNumber
530 )
531 {
532 EFI_STATUS Status;
533 BOOLEAN PeiExMapTableEmpty;
534 BOOLEAN DxeExMapTableEmpty;
535
536 if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {
537 return EFI_UNSUPPORTED;
538 }
539
540 Status = EFI_NOT_FOUND;
541 PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
542 DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;
543
544 //
545 // Scan the local token space
546 //
547 if (Guid == NULL) {
548 // EBC compiler is very choosy. It may report warning about comparison
549 // between UINTN and 0 . So we add 1 in each size of the
550 // comparison.
551 if (((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) && (*TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1)) ||
552 ((*TokenNumber + 1 > (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1)))) {
553 return EFI_NOT_FOUND;
554 }
555
556 (*TokenNumber)++;
557 if ((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) &&
558 (*TokenNumber <= PEI_LOCAL_TOKEN_NUMBER)) {
559 //
560 // The first Non-Ex type Token Number for DXE PCD
561 // database is PEI_LOCAL_TOKEN_NUMBER
562 //
563 *TokenNumber = PEI_LOCAL_TOKEN_NUMBER;
564 } else if (*TokenNumber + 1 > DXE_NEX_TOKEN_NUMBER + PEI_LOCAL_TOKEN_NUMBER + 1) {
565 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
566 }
567 return EFI_SUCCESS;
568 }
569
570 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
571 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
572 return EFI_NOT_FOUND;
573 }
574
575 if (!PeiExMapTableEmpty) {
576 Status = ExGetNextTokeNumber (
577 Guid,
578 TokenNumber,
579 mPcdDatabase->PeiDb.Init.GuidTable,
580 sizeof(mPcdDatabase->PeiDb.Init.GuidTable),
581 mPcdDatabase->PeiDb.Init.ExMapTable,
582 sizeof(mPcdDatabase->PeiDb.Init.ExMapTable)
583 );
584 }
585
586 if (Status == EFI_SUCCESS) {
587 return Status;
588 }
589
590 if (!DxeExMapTableEmpty) {
591 Status = ExGetNextTokeNumber (
592 Guid,
593 TokenNumber,
594 mPcdDatabase->DxeDb.Init.GuidTable,
595 sizeof(mPcdDatabase->DxeDb.Init.GuidTable),
596 mPcdDatabase->DxeDb.Init.ExMapTable,
597 sizeof(mPcdDatabase->DxeDb.Init.ExMapTable)
598 );
599 }
600
601 return Status;
602 }
603
604 STATIC
605 EFI_GUID **
606 GetDistinctTokenSpace (
607 IN OUT UINTN *ExMapTableSize,
608 IN DYNAMICEX_MAPPING *ExMapTable,
609 IN EFI_GUID *GuidTable
610 )
611 {
612 EFI_GUID **DistinctTokenSpace;
613 UINTN OldGuidIndex;
614 UINTN TsIdx;
615 UINTN Idx;
616
617
618 DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));
619 ASSERT (DistinctTokenSpace != NULL);
620
621 TsIdx = 0;
622 OldGuidIndex = ExMapTable[0].ExGuidIndex;
623 DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];
624 for (Idx = 1; Idx < *ExMapTableSize; Idx++) {
625 if (ExMapTable[Idx].ExGuidIndex != OldGuidIndex) {
626 OldGuidIndex = ExMapTable[Idx].ExGuidIndex;
627 DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];
628 }
629 }
630
631 //
632 // The total number of Distinct Token Space
633 // is TsIdx + 1 because we use TsIdx as a index
634 // to the DistinctTokenSpace[]
635 //
636 *ExMapTableSize = TsIdx + 1;
637 return DistinctTokenSpace;
638
639 }
640
641 //
642 // Just pre-allocate a memory buffer that is big enough to
643 // host all distinct TokenSpace guid in both
644 // PEI ExMap and DXE ExMap.
645 //
646 STATIC EFI_GUID *TmpTokenSpaceBuffer[PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE] = { 0 };
647
648 EFI_STATUS
649 EFIAPI
650 DxePcdGetNextTokenSpace (
651 IN OUT CONST EFI_GUID **Guid
652 )
653 {
654 UINTN Idx;
655 UINTN Idx2;
656 UINTN Idx3;
657 UINTN PeiTokenSpaceTableSize;
658 UINTN DxeTokenSpaceTableSize;
659 EFI_GUID **PeiTokenSpaceTable;
660 EFI_GUID **DxeTokenSpaceTable;
661 BOOLEAN Match;
662 BOOLEAN PeiExMapTableEmpty;
663 BOOLEAN DxeExMapTableEmpty;
664
665 if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {
666 return EFI_UNSUPPORTED;
667 }
668
669 ASSERT (Guid != NULL);
670
671 PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
672 DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;
673
674 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
675 if (*Guid != NULL) {
676 return EFI_NOT_FOUND;
677 } else {
678 return EFI_SUCCESS;
679 }
680 }
681
682
683 if (TmpTokenSpaceBuffer[0] == NULL) {
684 PeiTokenSpaceTableSize = 0;
685
686 if (!PeiExMapTableEmpty) {
687 PeiTokenSpaceTableSize = PEI_EXMAPPING_TABLE_SIZE;
688 PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize,
689 mPcdDatabase->PeiDb.Init.ExMapTable,
690 mPcdDatabase->PeiDb.Init.GuidTable
691 );
692 CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize);
693 }
694
695 if (!DxeExMapTableEmpty) {
696 DxeTokenSpaceTableSize = DXE_EXMAPPING_TABLE_SIZE;
697 DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize,
698 mPcdDatabase->DxeDb.Init.ExMapTable,
699 mPcdDatabase->DxeDb.Init.GuidTable
700 );
701
702 //
703 // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable
704 //
705 for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {
706 Match = FALSE;
707 for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {
708 if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {
709 Match = TRUE;
710 break;
711 }
712 }
713 if (!Match) {
714 TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];
715 }
716 }
717 }
718 }
719
720 if (*Guid == NULL) {
721 *Guid = TmpTokenSpaceBuffer[0];
722 return EFI_SUCCESS;
723 }
724
725 for (Idx = 0; Idx < (PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE); Idx++) {
726 if(CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {
727 Idx++;
728 *Guid = TmpTokenSpaceBuffer[Idx];
729 return EFI_SUCCESS;
730 }
731 }
732
733 return EFI_NOT_FOUND;
734
735 }
736
737