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