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