1. Sync the latest network stack. Add NetLibCreateIPv4DPathNode () in netlib library.
[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 #include "Service.h"
19
20 EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(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 BOOLEAN PeiExMapTableEmpty;
529 BOOLEAN DxeExMapTableEmpty;
530
531 if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {
532 return EFI_UNSUPPORTED;
533 }
534
535 Status = EFI_NOT_FOUND;
536 PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
537 DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;
538
539 //
540 // Scan the local token space
541 //
542 if (Guid == NULL) {
543 // EBC compiler is very choosy. It may report warning about comparison
544 // between UINTN and 0 . So we add 1 in each size of the
545 // comparison.
546 if (((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) && (*TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1)) ||
547 ((*TokenNumber + 1 > (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1)))) {
548 return EFI_NOT_FOUND;
549 }
550
551 (*TokenNumber)++;
552 if ((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) &&
553 (*TokenNumber <= PEI_LOCAL_TOKEN_NUMBER)) {
554 //
555 // The first Non-Ex type Token Number for DXE PCD
556 // database is PEI_LOCAL_TOKEN_NUMBER
557 //
558 *TokenNumber = PEI_LOCAL_TOKEN_NUMBER;
559 } else if (*TokenNumber + 1 > DXE_NEX_TOKEN_NUMBER + PEI_LOCAL_TOKEN_NUMBER + 1) {
560 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
561 }
562 return EFI_SUCCESS;
563 }
564
565 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
566 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
567 return EFI_NOT_FOUND;
568 }
569
570 if (!PeiExMapTableEmpty) {
571 Status = ExGetNextTokeNumber (
572 Guid,
573 TokenNumber,
574 mPcdDatabase->PeiDb.Init.GuidTable,
575 sizeof(mPcdDatabase->PeiDb.Init.GuidTable),
576 mPcdDatabase->PeiDb.Init.ExMapTable,
577 sizeof(mPcdDatabase->PeiDb.Init.ExMapTable)
578 );
579 }
580
581 if (Status == EFI_SUCCESS) {
582 return Status;
583 }
584
585 if (!DxeExMapTableEmpty) {
586 Status = ExGetNextTokeNumber (
587 Guid,
588 TokenNumber,
589 mPcdDatabase->DxeDb.Init.GuidTable,
590 sizeof(mPcdDatabase->DxeDb.Init.GuidTable),
591 mPcdDatabase->DxeDb.Init.ExMapTable,
592 sizeof(mPcdDatabase->DxeDb.Init.ExMapTable)
593 );
594 }
595
596 return Status;
597 }
598
599 STATIC
600 EFI_GUID **
601 GetDistinctTokenSpace (
602 IN OUT UINTN *ExMapTableSize,
603 IN DYNAMICEX_MAPPING *ExMapTable,
604 IN EFI_GUID *GuidTable
605 )
606 {
607 EFI_GUID **DistinctTokenSpace;
608 UINTN OldGuidIndex;
609 UINTN TsIdx;
610 UINTN Idx;
611
612
613 DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));
614 ASSERT (DistinctTokenSpace != NULL);
615
616 TsIdx = 0;
617 OldGuidIndex = ExMapTable[0].ExGuidIndex;
618 DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];
619 for (Idx = 1; Idx < *ExMapTableSize; Idx++) {
620 if (ExMapTable[Idx].ExGuidIndex != OldGuidIndex) {
621 OldGuidIndex = ExMapTable[Idx].ExGuidIndex;
622 DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];
623 }
624 }
625
626 //
627 // The total number of Distinct Token Space
628 // is TsIdx + 1 because we use TsIdx as a index
629 // to the DistinctTokenSpace[]
630 //
631 *ExMapTableSize = TsIdx + 1;
632 return DistinctTokenSpace;
633
634 }
635
636 //
637 // Just pre-allocate a memory buffer that is big enough to
638 // host all distinct TokenSpace guid in both
639 // PEI ExMap and DXE ExMap.
640 //
641 STATIC EFI_GUID *TmpTokenSpaceBuffer[PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE] = { 0 };
642
643 EFI_STATUS
644 EFIAPI
645 DxePcdGetNextTokenSpace (
646 IN OUT CONST EFI_GUID **Guid
647 )
648 {
649 UINTN Idx;
650 UINTN Idx2;
651 UINTN Idx3;
652 UINTN PeiTokenSpaceTableSize;
653 UINTN DxeTokenSpaceTableSize;
654 EFI_GUID **PeiTokenSpaceTable;
655 EFI_GUID **DxeTokenSpaceTable;
656 BOOLEAN Match;
657 BOOLEAN PeiExMapTableEmpty;
658 BOOLEAN DxeExMapTableEmpty;
659
660 if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {
661 return EFI_UNSUPPORTED;
662 }
663
664 ASSERT (Guid != NULL);
665
666 PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
667 DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;
668
669 if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
670 if (*Guid != NULL) {
671 return EFI_NOT_FOUND;
672 } else {
673 return EFI_SUCCESS;
674 }
675 }
676
677
678 if (TmpTokenSpaceBuffer[0] == NULL) {
679 PeiTokenSpaceTableSize = 0;
680
681 if (!PeiExMapTableEmpty) {
682 PeiTokenSpaceTableSize = PEI_EXMAPPING_TABLE_SIZE;
683 PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize,
684 mPcdDatabase->PeiDb.Init.ExMapTable,
685 mPcdDatabase->PeiDb.Init.GuidTable
686 );
687 CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize);
688 }
689
690 if (!DxeExMapTableEmpty) {
691 DxeTokenSpaceTableSize = DXE_EXMAPPING_TABLE_SIZE;
692 DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize,
693 mPcdDatabase->DxeDb.Init.ExMapTable,
694 mPcdDatabase->DxeDb.Init.GuidTable
695 );
696
697 //
698 // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable
699 //
700 for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {
701 Match = FALSE;
702 for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {
703 if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {
704 Match = TRUE;
705 break;
706 }
707 }
708 if (!Match) {
709 TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];
710 }
711 }
712 }
713 }
714
715 if (*Guid == NULL) {
716 *Guid = TmpTokenSpaceBuffer[0];
717 return EFI_SUCCESS;
718 }
719
720 for (Idx = 0; Idx < (PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE); Idx++) {
721 if(CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {
722 Idx++;
723 *Guid = TmpTokenSpaceBuffer[Idx];
724 return EFI_SUCCESS;
725 }
726 }
727
728 return EFI_NOT_FOUND;
729
730 }
731
732