]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp
21a479db68c29b6a4c0e54ebda705401bf8127ed
[mirror_edk2.git] / BaseTools / Source / C / VfrCompile / VfrUtilityLib.cpp
1 /** @file
2
3 Vfr common library functions.
4
5 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "stdio.h"
17 #include "stdlib.h"
18 #include "VfrUtilityLib.h"
19 #include "VfrFormPkg.h"
20
21 VOID
22 CVfrBinaryOutput::WriteLine (
23 IN FILE *pFile,
24 IN UINT32 LineBytes,
25 IN CONST CHAR8 *LineHeader,
26 IN CHAR8 *BlkBuf,
27 IN UINT32 BlkSize
28 )
29 {
30 UINT32 Index;
31
32 if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
33 return;
34 }
35
36 for (Index = 0; Index < BlkSize; Index++) {
37 if ((Index % LineBytes) == 0) {
38 fprintf (pFile, "\n%s", LineHeader);
39 }
40 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);
41 }
42 }
43
44 VOID
45 CVfrBinaryOutput::WriteEnd (
46 IN FILE *pFile,
47 IN UINT32 LineBytes,
48 IN CONST CHAR8 *LineHeader,
49 IN CHAR8 *BlkBuf,
50 IN UINT32 BlkSize
51 )
52 {
53 UINT32 Index;
54
55 if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
56 return;
57 }
58
59 for (Index = 0; Index < BlkSize - 1; Index++) {
60 if ((Index % LineBytes) == 0) {
61 fprintf (pFile, "\n%s", LineHeader);
62 }
63 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);
64 }
65
66 if ((Index % LineBytes) == 0) {
67 fprintf (pFile, "\n%s", LineHeader);
68 }
69 fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);
70 }
71
72 SConfigInfo::SConfigInfo (
73 IN UINT8 Type,
74 IN UINT16 Offset,
75 IN UINT32 Width,
76 IN EFI_IFR_TYPE_VALUE Value
77 )
78 {
79 mNext = NULL;
80 mOffset = Offset;
81 mWidth = (UINT16)Width;
82 mValue = new UINT8[mWidth];
83 if (mValue == NULL) {
84 return;
85 }
86
87 switch (Type) {
88 case EFI_IFR_TYPE_NUM_SIZE_8 :
89 memcpy (mValue, &Value.u8, mWidth);
90 break;
91 case EFI_IFR_TYPE_NUM_SIZE_16 :
92 memcpy (mValue, &Value.u16, mWidth);
93 break;
94 case EFI_IFR_TYPE_NUM_SIZE_32 :
95 memcpy (mValue, &Value.u32, mWidth);
96 break;
97 case EFI_IFR_TYPE_NUM_SIZE_64 :
98 memcpy (mValue, &Value.u64, mWidth);
99 break;
100 case EFI_IFR_TYPE_BOOLEAN :
101 memcpy (mValue, &Value.b, mWidth);
102 break;
103 case EFI_IFR_TYPE_TIME :
104 memcpy (mValue, &Value.time, mWidth);
105 break;
106 case EFI_IFR_TYPE_DATE :
107 memcpy (mValue, &Value.date, mWidth);
108 break;
109 case EFI_IFR_TYPE_STRING :
110 memcpy (mValue, &Value.string, mWidth);
111 break;
112 case EFI_IFR_TYPE_OTHER :
113 return;
114 }
115 }
116
117 SConfigInfo::~SConfigInfo (
118 VOID
119 )
120 {
121 BUFFER_SAFE_FREE (mValue);
122 }
123
124 SConfigItem::SConfigItem (
125 IN CHAR8 *Name,
126 IN EFI_GUID *Guid,
127 IN CHAR8 *Id
128 )
129 {
130 mName = NULL;
131 mGuid = NULL;
132 mId = NULL;
133 mInfoStrList = NULL;
134 mNext = NULL;
135
136 if (Name != NULL) {
137 if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) {
138 strcpy (mName, Name);
139 }
140 }
141
142 if (Guid != NULL) {
143 if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) {
144 memcpy (mGuid, Guid, sizeof (EFI_GUID));
145 }
146 }
147
148 if (Id != NULL) {
149 if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) {
150 strcpy (mId, Id);
151 }
152 }
153 }
154
155 SConfigItem::SConfigItem (
156 IN CHAR8 *Name,
157 IN EFI_GUID *Guid,
158 IN CHAR8 *Id,
159 IN UINT8 Type,
160 IN UINT16 Offset,
161 IN UINT16 Width,
162 IN EFI_IFR_TYPE_VALUE Value
163 )
164 {
165 mName = NULL;
166 mGuid = NULL;
167 mId = NULL;
168 mInfoStrList = NULL;
169 mNext = NULL;
170
171 if (Name != NULL) {
172 if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) {
173 strcpy (mName, Name);
174 }
175 }
176
177 if (Guid != NULL) {
178 if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) {
179 memcpy (mGuid, Guid, sizeof (EFI_GUID));
180 }
181 }
182
183 if (Id != NULL) {
184 if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) {
185 strcpy (mId, Id);
186 }
187 }
188
189 mInfoStrList = new SConfigInfo(Type, Offset, Width, Value);
190 }
191
192 SConfigItem::~SConfigItem (
193 VOID
194 )
195 {
196 SConfigInfo *Info;
197
198 BUFFER_SAFE_FREE (mName);
199 BUFFER_SAFE_FREE (mGuid);
200 BUFFER_SAFE_FREE (mId);
201 while (mInfoStrList != NULL) {
202 Info = mInfoStrList;
203 mInfoStrList = mInfoStrList->mNext;
204
205 BUFFER_SAFE_FREE (Info);
206 }
207 }
208
209 UINT8
210 CVfrBufferConfig::Register (
211 IN CHAR8 *Name,
212 IN EFI_GUID *Guid,
213 IN CHAR8 *Id
214 )
215 {
216 SConfigItem *pNew;
217
218 if (Select (Name, Guid) == 0) {
219 return 1;
220 }
221
222 if ((pNew = new SConfigItem (Name, Guid, Id)) == NULL) {
223 return 2;
224 }
225
226 if (mItemListHead == NULL) {
227 mItemListHead = pNew;
228 mItemListTail = pNew;
229 } else {
230 mItemListTail->mNext = pNew;
231 mItemListTail = pNew;
232 }
233 mItemListPos = pNew;
234
235 return 0;
236 }
237
238 VOID
239 CVfrBufferConfig::Open (
240 VOID
241 )
242 {
243 mItemListPos = mItemListHead;
244 }
245
246 BOOLEAN
247 CVfrBufferConfig::Eof(
248 VOID
249 )
250 {
251 return (mItemListPos == NULL) ? TRUE : FALSE;
252 }
253
254 UINT8
255 CVfrBufferConfig::Select (
256 IN CHAR8 *Name,
257 IN EFI_GUID *Guid,
258 IN CHAR8 *Id
259 )
260 {
261 SConfigItem *p;
262
263 if (Name == NULL || Guid == NULL) {
264 mItemListPos = mItemListHead;
265 return 0;
266 } else {
267 for (p = mItemListHead; p != NULL; p = p->mNext) {
268 if ((strcmp (p->mName, Name) != 0) || (memcmp (p->mGuid, Guid, sizeof (EFI_GUID)) != 0)) {
269 continue;
270 }
271
272 if (Id != NULL) {
273 if (p->mId == NULL || strcmp (p->mId, Id) != 0) {
274 continue;
275 }
276 } else if (p->mId != NULL) {
277 continue;
278 }
279
280 mItemListPos = p;
281 return 0;
282 }
283 }
284
285 return 1;
286 }
287
288 UINT8
289 CVfrBufferConfig::Write (
290 IN CONST CHAR8 Mode,
291 IN CHAR8 *Name,
292 IN EFI_GUID *Guid,
293 IN CHAR8 *Id,
294 IN UINT8 Type,
295 IN UINT16 Offset,
296 IN UINT32 Width,
297 IN EFI_IFR_TYPE_VALUE Value
298 )
299 {
300 UINT8 Ret;
301 SConfigItem *pItem;
302 SConfigInfo *pInfo;
303
304 if ((Ret = Select (Name, Guid)) != 0) {
305 return Ret;
306 }
307
308 switch (Mode) {
309 case 'a' : // add
310 if (Select (Name, Guid, Id) != 0) {
311 if ((pItem = new SConfigItem (Name, Guid, Id, Type, Offset, (UINT16) Width, Value)) == NULL) {
312 return 2;
313 }
314 if (mItemListHead == NULL) {
315 mItemListHead = pItem;
316 mItemListTail = pItem;
317 } else {
318 mItemListTail->mNext = pItem;
319 mItemListTail = pItem;
320 }
321 mItemListPos = pItem;
322 } else {
323 // tranverse the list to find out if there's already the value for the same offset
324 for (pInfo = mItemListPos->mInfoStrList; pInfo != NULL; pInfo = pInfo->mNext) {
325 if (pInfo->mOffset == Offset) {
326 return 0;
327 }
328 }
329 if((pInfo = new SConfigInfo (Type, Offset, Width, Value)) == NULL) {
330 return 2;
331 }
332 pInfo->mNext = mItemListPos->mInfoStrList;
333 mItemListPos->mInfoStrList = pInfo;
334 }
335 break;
336
337 case 'd' : // delete
338 if (mItemListHead == mItemListPos) {
339 mItemListHead = mItemListPos->mNext;
340 delete mItemListPos;
341 break;
342 }
343
344 for (pItem = mItemListHead; pItem->mNext != mItemListPos; pItem = pItem->mNext)
345 ;
346
347 pItem->mNext = mItemListPos->mNext;
348 if (mItemListTail == mItemListPos) {
349 mItemListTail = pItem;
350 }
351 delete mItemListPos;
352 mItemListPos = pItem->mNext;
353 break;
354
355 case 'i' : // set info
356 if (mItemListPos->mId != NULL) {
357 delete mItemListPos->mId;
358 }
359 mItemListPos->mId = NULL;
360 if (Id != NULL) {
361 if ((mItemListPos->mId = new CHAR8[strlen (Id) + 1]) == NULL) {
362 return 2;
363 }
364 strcpy (mItemListPos->mId, Id);
365 }
366 break;
367
368 default :
369 return 1;
370 }
371
372 return 0;
373 }
374
375
376 VOID
377 CVfrBufferConfig::Close (
378 VOID
379 )
380 {
381 mItemListPos = NULL;
382 }
383
384 #define BYTES_PRE_LINE 0x10
385
386 VOID
387 CVfrBufferConfig::OutputCFile (
388 IN FILE *pFile,
389 IN CHAR8 *BaseName
390 )
391 {
392 CVfrBinaryOutput Output;
393 SConfigItem *Item;
394 SConfigInfo *Info;
395 UINT32 TotalLen;
396
397 if (pFile == NULL) {
398 return;
399 }
400
401 for (Item = mItemListHead; Item != NULL; Item = Item->mNext) {
402 if (Item->mId != NULL || Item->mInfoStrList == NULL) {
403 continue;
404 }
405 fprintf (pFile, "\nunsigned char %s%sBlockName[] = {", BaseName, Item->mName);
406
407 TotalLen = sizeof (UINT32);
408 for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
409 TotalLen += sizeof (UINT16) * 2;
410 }
411 Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32));
412
413 for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
414 fprintf (pFile, "\n");
415 Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16));
416 Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16));
417 }
418 fprintf (pFile, "\n};\n");
419 }
420
421 for (Item = mItemListHead; Item != NULL; Item = Item->mNext) {
422 if (Item->mId != NULL && Item->mInfoStrList != NULL) {
423 fprintf (pFile, "\nunsigned char %s%sDefault%s[] = {", BaseName, Item->mName, Item->mId);
424
425 TotalLen = sizeof (UINT32);
426 for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
427 TotalLen += Info->mWidth + sizeof (UINT16) * 2;
428 }
429 Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32));
430
431 for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) {
432 fprintf (pFile, "\n");
433 Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16));
434 Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16));
435 if (Info->mNext == NULL) {
436 Output.WriteEnd (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth);
437 } else {
438 Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth);
439 }
440 }
441 fprintf (pFile, "\n};\n");
442 }
443 }
444 }
445
446 CVfrBufferConfig::CVfrBufferConfig (
447 VOID
448 )
449 {
450 mItemListHead = NULL;
451 mItemListTail = NULL;
452 mItemListPos = NULL;
453 }
454
455 CVfrBufferConfig::~CVfrBufferConfig (
456 VOID
457 )
458 {
459 SConfigItem *p;
460
461 while (mItemListHead != NULL) {
462 p = mItemListHead;
463 mItemListHead = mItemListHead->mNext;
464 delete p;
465 }
466
467 mItemListHead = NULL;
468 mItemListTail = NULL;
469 mItemListPos = NULL;
470 }
471
472 CVfrBufferConfig gCVfrBufferConfig;
473
474 static struct {
475 CONST CHAR8 *mTypeName;
476 UINT8 mType;
477 UINT32 mSize;
478 UINT32 mAlign;
479 } gInternalTypesTable [] = {
480 {"UINT64", EFI_IFR_TYPE_NUM_SIZE_64, sizeof (UINT64), sizeof (UINT64)},
481 {"UINT32", EFI_IFR_TYPE_NUM_SIZE_32, sizeof (UINT32), sizeof (UINT32)},
482 {"UINT16", EFI_IFR_TYPE_NUM_SIZE_16, sizeof (UINT16), sizeof (UINT16)},
483 {"UINT8", EFI_IFR_TYPE_NUM_SIZE_8, sizeof (UINT8), sizeof (UINT8)},
484 {"BOOLEAN", EFI_IFR_TYPE_BOOLEAN, sizeof (BOOLEAN), sizeof (BOOLEAN)},
485 {"EFI_HII_DATE", EFI_IFR_TYPE_DATE, sizeof (EFI_HII_DATE), sizeof (UINT16)},
486 {"EFI_STRING_ID", EFI_IFR_TYPE_STRING, sizeof (EFI_STRING_ID),sizeof (EFI_STRING_ID)},
487 {"EFI_HII_TIME", EFI_IFR_TYPE_TIME, sizeof (EFI_HII_TIME), sizeof (UINT8)},
488 {"EFI_HII_REF", EFI_IFR_TYPE_REF, sizeof (EFI_HII_REF), sizeof (EFI_GUID)},
489 {NULL, EFI_IFR_TYPE_OTHER, 0, 0}
490 };
491
492 STATIC
493 BOOLEAN
494 _IS_INTERNAL_TYPE (
495 IN CHAR8 *TypeName
496 )
497 {
498 UINT32 Index;
499
500 if (TypeName == NULL) {
501 return FALSE;
502 }
503
504 for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) {
505 if (strcmp (TypeName, gInternalTypesTable[Index].mTypeName) == 0) {
506 return TRUE;
507 }
508 }
509
510 return FALSE;
511 }
512
513 STATIC
514 CHAR8 *
515 TrimHex (
516 IN CHAR8 *Str,
517 OUT bool *IsHex
518 )
519 {
520 *IsHex = FALSE;
521
522 while (*Str && *Str == ' ') {
523 Str++;
524 }
525 while (*Str && *Str == '0') {
526 Str++;
527 }
528 if (*Str && (*Str == 'x' || *Str == 'X')) {
529 Str++;
530 *IsHex = TRUE;
531 }
532
533 return Str;
534 }
535
536 UINT32
537 _STR2U32 (
538 IN CHAR8 *Str
539 )
540 {
541 bool IsHex;
542 UINT32 Value;
543 CHAR8 c;
544
545 Str = TrimHex (Str, &IsHex);
546 for (Value = 0; (c = *Str) != '\0'; Str++) {
547 //
548 // BUG: does not handle overflow here
549 //
550 (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10);
551
552 if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) {
553 Value += (c - 'a' + 10);
554 }
555 if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) {
556 Value += (c - 'A' + 10);
557 }
558 if (c >= '0' && c <= '9') {
559 Value += (c - '0');
560 }
561 }
562
563 return Value;
564 }
565
566 VOID
567 CVfrVarDataTypeDB::RegisterNewType (
568 IN SVfrDataType *New
569 )
570 {
571 New->mNext = mDataTypeList;
572 mDataTypeList = New;
573 }
574
575 EFI_VFR_RETURN_CODE
576 CVfrVarDataTypeDB::ExtractStructTypeName (
577 IN CHAR8 *&VarStr,
578 OUT CHAR8 *TName
579 )
580 {
581 if (TName == NULL) {
582 return VFR_RETURN_FATAL_ERROR;
583 }
584
585 while((*VarStr != '\0') && (*VarStr != '.')) {
586 *TName = *VarStr;
587 VarStr++;
588 TName++;
589 }
590 *TName = '\0';
591 if (*VarStr == '.') {
592 VarStr++;
593 }
594
595 return VFR_RETURN_SUCCESS;
596 }
597
598 EFI_VFR_RETURN_CODE
599 CVfrVarDataTypeDB::ExtractFieldNameAndArrary (
600 IN CHAR8 *&VarStr,
601 IN CHAR8 *FName,
602 OUT UINT32 &ArrayIdx
603 )
604 {
605 UINT32 Idx;
606 CHAR8 ArrayStr[MAX_NAME_LEN + 1];
607
608 ArrayIdx = INVALID_ARRAY_INDEX;
609
610 if (FName == NULL) {
611 return VFR_RETURN_FATAL_ERROR;
612 }
613
614 while((*VarStr != '\0') &&
615 (*VarStr != '.') &&
616 (*VarStr != '[') &&
617 (*VarStr != ']')) {
618 *FName = *VarStr;
619 VarStr++;
620 FName++;
621 }
622 *FName = '\0';
623
624 switch (*VarStr) {
625 case '.' :
626 VarStr++;
627 case '\0':
628 return VFR_RETURN_SUCCESS;
629 case '[' :
630 VarStr++;
631 for (Idx = 0; (Idx < MAX_NAME_LEN) && (*VarStr != '\0') && (*VarStr != ']'); VarStr++, Idx++) {
632 ArrayStr[Idx] = *VarStr;
633 }
634 ArrayStr[Idx] = '\0';
635
636 if ((*VarStr != ']') && (ArrayStr[0] == '\0')) {
637 return VFR_RETURN_DATA_STRING_ERROR;
638 }
639 ArrayIdx = _STR2U32 (ArrayStr);
640 if (*VarStr == ']') {
641 VarStr++;
642 }
643 if (*VarStr == '.') {
644 VarStr++;
645 }
646 return VFR_RETURN_SUCCESS;
647 case ']':
648 return VFR_RETURN_DATA_STRING_ERROR;
649 }
650
651 return VFR_RETURN_SUCCESS;
652 }
653
654 EFI_VFR_RETURN_CODE
655 CVfrVarDataTypeDB::GetTypeField (
656 IN CONST CHAR8 *FName,
657 IN SVfrDataType *Type,
658 OUT SVfrDataField *&Field
659 )
660 {
661 SVfrDataField *pField = NULL;
662
663 if ((FName == NULL) && (Type == NULL)) {
664 return VFR_RETURN_FATAL_ERROR;
665 }
666
667 for (pField = Type->mMembers; pField != NULL; pField = pField->mNext) {
668 //
669 // For type EFI_IFR_TYPE_TIME, because field name is not correctly wrote,
670 // add code to adjust it.
671 //
672 if (Type->mType == EFI_IFR_TYPE_TIME) {
673 if (strcmp (FName, "Hour") == 0) {
674 FName = "Hours";
675 } else if (strcmp (FName, "Minute") == 0) {
676 FName = "Minuts";
677 } else if (strcmp (FName, "Second") == 0) {
678 FName = "Seconds";
679 }
680 }
681
682 if (strcmp (pField->mFieldName, FName) == 0) {
683 Field = pField;
684 return VFR_RETURN_SUCCESS;
685 }
686 }
687
688 return VFR_RETURN_UNDEFINED;
689 }
690
691 EFI_VFR_RETURN_CODE
692 CVfrVarDataTypeDB::GetFieldOffset (
693 IN SVfrDataField *Field,
694 IN UINT32 ArrayIdx,
695 OUT UINT32 &Offset
696 )
697 {
698 if (Field == NULL) {
699 return VFR_RETURN_FATAL_ERROR;
700 }
701
702 //
703 // Framework Vfr file Array Index is from 1.
704 // But Uefi Vfr file Array Index is from 0.
705 //
706 if (VfrCompatibleMode && ArrayIdx != INVALID_ARRAY_INDEX) {
707 if (ArrayIdx == 0) {
708 return VFR_RETURN_ERROR_ARRARY_NUM;
709 }
710 ArrayIdx = ArrayIdx - 1;
711 }
712
713 if ((ArrayIdx != INVALID_ARRAY_INDEX) && ((Field->mArrayNum == 0) || (Field->mArrayNum <= ArrayIdx))) {
714 return VFR_RETURN_ERROR_ARRARY_NUM;
715 }
716
717 //
718 // Be compatible with the current usage
719 // If ArraryIdx is not specified, the first one is used.
720 //
721 // if ArrayNum is larger than zero, ArraryIdx must be specified.
722 //
723 // if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum > 0)) {
724 // return VFR_RETURN_ERROR_ARRARY_NUM;
725 // }
726 //
727
728 Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx);
729 return VFR_RETURN_SUCCESS;
730 }
731
732 UINT8
733 CVfrVarDataTypeDB::GetFieldWidth (
734 IN SVfrDataField *Field
735 )
736 {
737 if (Field == NULL) {
738 return 0;
739 }
740
741 return Field->mFieldType->mType;
742 }
743
744 UINT32
745 CVfrVarDataTypeDB::GetFieldSize (
746 IN SVfrDataField *Field,
747 IN UINT32 ArrayIdx
748 )
749 {
750 if (Field == NULL) {
751 return VFR_RETURN_FATAL_ERROR;
752 }
753
754 if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum != 0)) {
755 return Field->mFieldType->mTotalSize * Field->mArrayNum;
756 } else {
757 return Field->mFieldType->mTotalSize;
758 }
759 }
760
761 VOID
762 CVfrVarDataTypeDB::InternalTypesListInit (
763 VOID
764 )
765 {
766 SVfrDataType *New = NULL;
767 UINT32 Index;
768
769 for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) {
770 New = new SVfrDataType;
771 if (New != NULL) {
772 strcpy (New->mTypeName, gInternalTypesTable[Index].mTypeName);
773 New->mType = gInternalTypesTable[Index].mType;
774 New->mAlign = gInternalTypesTable[Index].mAlign;
775 New->mTotalSize = gInternalTypesTable[Index].mSize;
776 if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_DATE") == 0) {
777 SVfrDataField *pYearField = new SVfrDataField;
778 SVfrDataField *pMonthField = new SVfrDataField;
779 SVfrDataField *pDayField = new SVfrDataField;
780
781 strcpy (pYearField->mFieldName, "Year");
782 GetDataType ((CHAR8 *)"UINT16", &pYearField->mFieldType);
783 pYearField->mOffset = 0;
784 pYearField->mNext = pMonthField;
785 pYearField->mArrayNum = 0;
786
787 strcpy (pMonthField->mFieldName, "Month");
788 GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType);
789 pMonthField->mOffset = 2;
790 pMonthField->mNext = pDayField;
791 pMonthField->mArrayNum = 0;
792
793 strcpy (pDayField->mFieldName, "Day");
794 GetDataType ((CHAR8 *)"UINT8", &pDayField->mFieldType);
795 pDayField->mOffset = 3;
796 pDayField->mNext = NULL;
797 pDayField->mArrayNum = 0;
798
799 New->mMembers = pYearField;
800 } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_TIME") == 0) {
801 SVfrDataField *pHoursField = new SVfrDataField;
802 SVfrDataField *pMinutesField = new SVfrDataField;
803 SVfrDataField *pSecondsField = new SVfrDataField;
804
805 strcpy (pHoursField->mFieldName, "Hours");
806 GetDataType ((CHAR8 *)"UINT8", &pHoursField->mFieldType);
807 pHoursField->mOffset = 0;
808 pHoursField->mNext = pMinutesField;
809 pHoursField->mArrayNum = 0;
810
811 strcpy (pMinutesField->mFieldName, "Minutes");
812 GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType);
813 pMinutesField->mOffset = 1;
814 pMinutesField->mNext = pSecondsField;
815 pMinutesField->mArrayNum = 0;
816
817 strcpy (pSecondsField->mFieldName, "Seconds");
818 GetDataType ((CHAR8 *)"UINT8", &pSecondsField->mFieldType);
819 pSecondsField->mOffset = 2;
820 pSecondsField->mNext = NULL;
821 pSecondsField->mArrayNum = 0;
822
823 New->mMembers = pHoursField;
824 } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_REF") == 0) {
825 SVfrDataField *pQuestionIdField = new SVfrDataField;
826 SVfrDataField *pFormIdField = new SVfrDataField;
827 SVfrDataField *pFormSetGuidField = new SVfrDataField;
828 SVfrDataField *pDevicePathField = new SVfrDataField;
829
830 strcpy (pQuestionIdField->mFieldName, "QuestionId");
831 GetDataType ((CHAR8 *)"UINT16", &pQuestionIdField->mFieldType);
832 pQuestionIdField->mOffset = 0;
833 pQuestionIdField->mNext = pFormIdField;
834 pQuestionIdField->mArrayNum = 0;
835
836 strcpy (pFormIdField->mFieldName, "FormId");
837 GetDataType ((CHAR8 *)"UINT16", &pFormIdField->mFieldType);
838 pFormIdField->mOffset = 2;
839 pFormIdField->mNext = pFormSetGuidField;
840 pFormIdField->mArrayNum = 0;
841
842 strcpy (pFormSetGuidField->mFieldName, "FormSetGuid");
843 GetDataType ((CHAR8 *)"EFI_GUID", &pFormSetGuidField->mFieldType);
844 pFormSetGuidField->mOffset = 4;
845 pFormSetGuidField->mNext = pDevicePathField;
846 pFormSetGuidField->mArrayNum = 0;
847
848 strcpy (pDevicePathField->mFieldName, "DevicePath");
849 GetDataType ((CHAR8 *)"EFI_STRING_ID", &pDevicePathField->mFieldType);
850 pDevicePathField->mOffset = 20;
851 pDevicePathField->mNext = NULL;
852 pDevicePathField->mArrayNum = 0;
853
854 New->mMembers = pQuestionIdField;
855 } else {
856 New->mMembers = NULL;
857 }
858 New->mNext = NULL;
859 RegisterNewType (New);
860 New = NULL;
861 }
862 }
863 }
864
865 CVfrVarDataTypeDB::CVfrVarDataTypeDB (
866 VOID
867 )
868 {
869 mDataTypeList = NULL;
870 mNewDataType = NULL;
871 mCurrDataField = NULL;
872 mPackAlign = DEFAULT_PACK_ALIGN;
873 mPackStack = NULL;
874 mFirstNewDataTypeName = NULL;
875
876 InternalTypesListInit ();
877 }
878
879 CVfrVarDataTypeDB::~CVfrVarDataTypeDB (
880 VOID
881 )
882 {
883 SVfrDataType *pType;
884 SVfrDataField *pField;
885 SVfrPackStackNode *pPack;
886
887 if (mNewDataType != NULL) {
888 delete mNewDataType;
889 }
890
891 while (mDataTypeList != NULL) {
892 pType = mDataTypeList;
893 mDataTypeList = mDataTypeList->mNext;
894 while(pType->mMembers != NULL) {
895 pField = pType->mMembers;
896 pType->mMembers = pType->mMembers->mNext;
897 delete pField;
898 }
899 delete pType;
900 }
901
902 while (mPackStack != NULL) {
903 pPack = mPackStack;
904 mPackStack = mPackStack->mNext;
905 delete pPack;
906 }
907 }
908
909 EFI_VFR_RETURN_CODE
910 CVfrVarDataTypeDB::Pack (
911 IN UINT32 LineNum,
912 IN UINT8 Action,
913 IN CHAR8 *Identifier,
914 IN UINT32 Number
915 )
916 {
917 UINT32 PackAlign;
918 CHAR8 Msg[MAX_STRING_LEN] = {0, };
919
920 if (Action & VFR_PACK_SHOW) {
921 sprintf (Msg, "value of pragma pack(show) == %d", mPackAlign);
922 gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Warning", Msg);
923 }
924
925 if (Action & VFR_PACK_PUSH) {
926 SVfrPackStackNode *pNew = NULL;
927
928 if ((pNew = new SVfrPackStackNode (Identifier, mPackAlign)) == NULL) {
929 return VFR_RETURN_FATAL_ERROR;
930 }
931 pNew->mNext = mPackStack;
932 mPackStack = pNew;
933 }
934
935 if (Action & VFR_PACK_POP) {
936 SVfrPackStackNode *pNode = NULL;
937
938 if (mPackStack == NULL) {
939 gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "#pragma pack(pop...) : more pops than pushes");
940 }
941
942 for (pNode = mPackStack; pNode != NULL; pNode = pNode->mNext) {
943 if (pNode->Match (Identifier) == TRUE) {
944 mPackAlign = pNode->mNumber;
945 mPackStack = pNode->mNext;
946 }
947 }
948 }
949
950 if (Action & VFR_PACK_ASSIGN) {
951 PackAlign = (Number > 1) ? Number + Number % 2 : Number;
952 if ((PackAlign == 0) || (PackAlign > 16)) {
953 gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "expected pragma parameter to be '1', '2', '4', '8', or '16'");
954 } else {
955 mPackAlign = PackAlign;
956 }
957 }
958
959 return VFR_RETURN_SUCCESS;
960 }
961
962 VOID
963 CVfrVarDataTypeDB::DeclareDataTypeBegin (
964 VOID
965 )
966 {
967 SVfrDataType *pNewType = NULL;
968
969 pNewType = new SVfrDataType;
970 pNewType->mTypeName[0] = '\0';
971 pNewType->mType = EFI_IFR_TYPE_OTHER;
972 pNewType->mAlign = DEFAULT_ALIGN;
973 pNewType->mTotalSize = 0;
974 pNewType->mMembers = NULL;
975 pNewType->mNext = NULL;
976
977 mNewDataType = pNewType;
978 }
979
980 EFI_VFR_RETURN_CODE
981 CVfrVarDataTypeDB::SetNewTypeName (
982 IN CHAR8 *TypeName
983 )
984 {
985 SVfrDataType *pType;
986
987 if (mNewDataType == NULL) {
988 return VFR_RETURN_ERROR_SKIPED;
989 }
990 if (TypeName == NULL) {
991 return VFR_RETURN_FATAL_ERROR;
992 }
993 if (strlen(TypeName) >= MAX_NAME_LEN) {
994 return VFR_RETURN_INVALID_PARAMETER;
995 }
996
997 for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) {
998 if (strcmp(pType->mTypeName, TypeName) == 0) {
999 return VFR_RETURN_REDEFINED;
1000 }
1001 }
1002
1003 strcpy(mNewDataType->mTypeName, TypeName);
1004 return VFR_RETURN_SUCCESS;
1005 }
1006
1007 EFI_VFR_RETURN_CODE
1008 CVfrVarDataTypeDB::DataTypeAddField (
1009 IN CHAR8 *FieldName,
1010 IN CHAR8 *TypeName,
1011 IN UINT32 ArrayNum
1012 )
1013 {
1014 SVfrDataField *pNewField = NULL;
1015 SVfrDataType *pFieldType = NULL;
1016 SVfrDataField *pTmp;
1017 UINT32 Align;
1018
1019 CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS);
1020
1021 if (strlen (FieldName) >= MAX_NAME_LEN) {
1022 return VFR_RETURN_INVALID_PARAMETER;
1023 }
1024
1025 for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) {
1026 if (strcmp (pTmp->mFieldName, FieldName) == 0) {
1027 return VFR_RETURN_REDEFINED;
1028 }
1029 }
1030
1031 Align = MIN (mPackAlign, pFieldType->mAlign);
1032
1033 if ((pNewField = new SVfrDataField) == NULL) {
1034 return VFR_RETURN_OUT_FOR_RESOURCES;
1035 }
1036 strcpy (pNewField->mFieldName, FieldName);
1037 pNewField->mFieldType = pFieldType;
1038 pNewField->mArrayNum = ArrayNum;
1039 if ((mNewDataType->mTotalSize % Align) == 0) {
1040 pNewField->mOffset = mNewDataType->mTotalSize;
1041 } else {
1042 pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align);
1043 }
1044 if (mNewDataType->mMembers == NULL) {
1045 mNewDataType->mMembers = pNewField;
1046 pNewField->mNext = NULL;
1047 } else {
1048 for (pTmp = mNewDataType->mMembers; pTmp->mNext != NULL; pTmp = pTmp->mNext)
1049 ;
1050 pTmp->mNext = pNewField;
1051 pNewField->mNext = NULL;
1052 }
1053
1054 mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign));
1055 mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum);
1056
1057 return VFR_RETURN_SUCCESS;
1058 }
1059
1060 VOID
1061 CVfrVarDataTypeDB::DeclareDataTypeEnd (
1062 VOID
1063 )
1064 {
1065 if (mNewDataType->mTypeName[0] == '\0') {
1066 return;
1067 }
1068
1069 if ((mNewDataType->mTotalSize % mNewDataType->mAlign) !=0) {
1070 mNewDataType->mTotalSize += ALIGN_STUFF (mNewDataType->mTotalSize, mNewDataType->mAlign);
1071 }
1072
1073 RegisterNewType (mNewDataType);
1074 if (mFirstNewDataTypeName == NULL) {
1075 mFirstNewDataTypeName = mNewDataType->mTypeName;
1076 }
1077
1078 mNewDataType = NULL;
1079 }
1080
1081 EFI_VFR_RETURN_CODE
1082 CVfrVarDataTypeDB::GetDataType (
1083 IN CHAR8 *TypeName,
1084 OUT SVfrDataType **DataType
1085 )
1086 {
1087 SVfrDataType *pDataType = NULL;
1088
1089 if (TypeName == NULL) {
1090 return VFR_RETURN_ERROR_SKIPED;
1091 }
1092
1093 if (DataType == NULL) {
1094 return VFR_RETURN_FATAL_ERROR;
1095 }
1096
1097 *DataType = NULL;
1098
1099 for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) {
1100 if (strcmp (TypeName, pDataType->mTypeName) == 0) {
1101 *DataType = pDataType;
1102 return VFR_RETURN_SUCCESS;
1103 }
1104 }
1105
1106 return VFR_RETURN_UNDEFINED;
1107 }
1108
1109 EFI_VFR_RETURN_CODE
1110 CVfrVarDataTypeDB::GetDataTypeSize (
1111 IN UINT8 DataType,
1112 OUT UINT32 *Size
1113 )
1114 {
1115 SVfrDataType *pDataType = NULL;
1116
1117 if (Size == NULL) {
1118 return VFR_RETURN_FATAL_ERROR;
1119 }
1120
1121 *Size = 0;
1122 DataType = DataType & 0x0F;
1123
1124 //
1125 // For user defined data type, the size can't be got by this function.
1126 //
1127 if (DataType == EFI_IFR_TYPE_OTHER) {
1128 return VFR_RETURN_SUCCESS;
1129 }
1130
1131 for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) {
1132 if (DataType == pDataType->mType) {
1133 *Size = pDataType->mTotalSize;
1134 return VFR_RETURN_SUCCESS;
1135 }
1136 }
1137
1138 return VFR_RETURN_UNDEFINED;
1139 }
1140
1141 EFI_VFR_RETURN_CODE
1142 CVfrVarDataTypeDB::GetDataTypeSize (
1143 IN CHAR8 *TypeName,
1144 OUT UINT32 *Size
1145 )
1146 {
1147 SVfrDataType *pDataType = NULL;
1148
1149 if (Size == NULL) {
1150 return VFR_RETURN_FATAL_ERROR;
1151 }
1152
1153 *Size = 0;
1154
1155 for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) {
1156 if (strcmp (TypeName, pDataType->mTypeName) == 0) {
1157 *Size = pDataType->mTotalSize;
1158 return VFR_RETURN_SUCCESS;
1159 }
1160 }
1161
1162 return VFR_RETURN_UNDEFINED;
1163 }
1164
1165 EFI_VFR_RETURN_CODE
1166 CVfrVarDataTypeDB::GetDataFieldInfo (
1167 IN CHAR8 *VarStr,
1168 OUT UINT16 &Offset,
1169 OUT UINT8 &Type,
1170 OUT UINT32 &Size
1171 )
1172 {
1173 CHAR8 TName[MAX_NAME_LEN], FName[MAX_NAME_LEN];
1174 UINT32 ArrayIdx, Tmp;
1175 SVfrDataType *pType = NULL;
1176 SVfrDataField *pField = NULL;
1177
1178 Offset = 0;
1179 Type = EFI_IFR_TYPE_OTHER;
1180 Size = 0;
1181
1182 CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS);
1183 CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS);
1184
1185 //
1186 // if it is not struct data type
1187 //
1188 Type = pType->mType;
1189 Size = pType->mTotalSize;
1190
1191 while (*VarStr != '\0') {
1192 CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS);
1193 CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS);
1194 pType = pField->mFieldType;
1195 CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp), VFR_RETURN_SUCCESS);
1196 Offset = (UINT16) (Offset + Tmp);
1197 Type = GetFieldWidth (pField);
1198 Size = GetFieldSize (pField, ArrayIdx);
1199 }
1200 return VFR_RETURN_SUCCESS;
1201 }
1202
1203 EFI_VFR_RETURN_CODE
1204 CVfrVarDataTypeDB::GetUserDefinedTypeNameList (
1205 OUT CHAR8 ***NameList,
1206 OUT UINT32 *ListSize
1207 )
1208 {
1209 UINT32 Index;
1210 SVfrDataType *pType;
1211
1212 if ((NameList == NULL) || (ListSize == NULL)) {
1213 return VFR_RETURN_FATAL_ERROR;
1214 }
1215
1216 *NameList = NULL;
1217 *ListSize = 0;
1218
1219 for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) {
1220 if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) {
1221 (*ListSize)++;
1222 }
1223 }
1224
1225 if (*ListSize == 0) {
1226 return VFR_RETURN_SUCCESS;
1227 }
1228
1229 if ((*NameList = new CHAR8*[*ListSize]) == NULL) {
1230 *ListSize = 0;
1231 return VFR_RETURN_OUT_FOR_RESOURCES;
1232 }
1233
1234 for (Index = 0, pType = mDataTypeList; pType != NULL; pType = pType->mNext, Index++) {
1235 if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) {
1236 (*NameList)[Index] = pType->mTypeName;
1237 }
1238 }
1239 return VFR_RETURN_SUCCESS;
1240 }
1241
1242 BOOLEAN
1243 CVfrVarDataTypeDB::IsTypeNameDefined (
1244 IN CHAR8 *TypeName
1245 )
1246 {
1247 SVfrDataType *pType;
1248
1249 if (TypeName == NULL) {
1250 return FALSE;
1251 }
1252
1253 for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) {
1254 if (strcmp (pType->mTypeName, TypeName) == 0) {
1255 return TRUE;
1256 }
1257 }
1258
1259 return FALSE;
1260 }
1261
1262 VOID
1263 CVfrVarDataTypeDB::Dump (
1264 IN FILE *File
1265 )
1266 {
1267 SVfrDataType *pTNode;
1268 SVfrDataField *pFNode;
1269
1270 fprintf (File, "\n\n***************************************************************\n");
1271 fprintf (File, "\t\tmPackAlign = %x\n", mPackAlign);
1272 for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) {
1273 fprintf (File, "\t\tstruct %s : mAlign [%d] mTotalSize [0x%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize);
1274 fprintf (File, "\t\tstruct %s {\n", pTNode->mTypeName);
1275 for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) {
1276 if (pFNode->mArrayNum > 0) {
1277 fprintf (File, "\t\t\t+%08d[%08x] %s[%d] <%s>\n", pFNode->mOffset, pFNode->mOffset,
1278 pFNode->mFieldName, pFNode->mArrayNum, pFNode->mFieldType->mTypeName);
1279 } else {
1280 fprintf (File, "\t\t\t+%08d[%08x] %s <%s>\n", pFNode->mOffset, pFNode->mOffset,
1281 pFNode->mFieldName, pFNode->mFieldType->mTypeName);
1282 }
1283 }
1284 fprintf (File, "\t\t};\n");
1285 fprintf (File, "---------------------------------------------------------------\n");
1286 }
1287 fprintf (File, "***************************************************************\n");
1288 }
1289
1290 #ifdef CVFR_VARDATATYPEDB_DEBUG
1291 VOID
1292 CVfrVarDataTypeDB::ParserDB (
1293 VOID
1294 )
1295 {
1296 SVfrDataType *pTNode;
1297 SVfrDataField *pFNode;
1298
1299 printf ("***************************************************************\n");
1300 printf ("\t\tmPackAlign = %x\n", mPackAlign);
1301 for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) {
1302 printf ("\t\tstruct %s : mAlign [%x] mTotalSize [%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize);
1303 printf ("\t\tstruct %s {\n", pTNode->mTypeName);
1304 for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) {
1305 printf ("\t\t\t%s\t%s\n", pFNode->mFieldType->mTypeName, pFNode->mFieldName);
1306 }
1307 printf ("\t\t};\n");
1308 printf ("---------------------------------------------------------------\n");
1309 }
1310 printf ("***************************************************************\n");
1311 }
1312 #endif
1313
1314 SVfrVarStorageNode::SVfrVarStorageNode (
1315 IN EFI_GUID *Guid,
1316 IN CHAR8 *StoreName,
1317 IN EFI_VARSTORE_ID VarStoreId,
1318 IN EFI_STRING_ID VarName,
1319 IN UINT32 VarSize,
1320 IN BOOLEAN Flag
1321 )
1322 {
1323 if (Guid != NULL) {
1324 mGuid = *Guid;
1325 } else {
1326 memset (&Guid, 0, sizeof (EFI_GUID));
1327 }
1328 if (StoreName != NULL) {
1329 mVarStoreName = new CHAR8[strlen(StoreName) + 1];
1330 strcpy (mVarStoreName, StoreName);
1331 } else {
1332 mVarStoreName = NULL;
1333 }
1334 mNext = NULL;
1335 mVarStoreId = VarStoreId;
1336 mVarStoreType = EFI_VFR_VARSTORE_EFI;
1337 mStorageInfo.mEfiVar.mEfiVarName = VarName;
1338 mStorageInfo.mEfiVar.mEfiVarSize = VarSize;
1339 mAssignedFlag = Flag;
1340 }
1341
1342 SVfrVarStorageNode::SVfrVarStorageNode (
1343 IN EFI_GUID *Guid,
1344 IN CHAR8 *StoreName,
1345 IN EFI_VARSTORE_ID VarStoreId,
1346 IN SVfrDataType *DataType,
1347 IN BOOLEAN Flag
1348 )
1349 {
1350 if (Guid != NULL) {
1351 mGuid = *Guid;
1352 } else {
1353 memset (&Guid, 0, sizeof (EFI_GUID));
1354 }
1355 if (StoreName != NULL) {
1356 mVarStoreName = new CHAR8[strlen(StoreName) + 1];
1357 strcpy (mVarStoreName, StoreName);
1358 } else {
1359 mVarStoreName = NULL;
1360 }
1361 mNext = NULL;
1362 mVarStoreId = VarStoreId;
1363 mVarStoreType = EFI_VFR_VARSTORE_BUFFER;
1364 mStorageInfo.mDataType = DataType;
1365 mAssignedFlag = Flag;
1366 }
1367
1368 SVfrVarStorageNode::SVfrVarStorageNode (
1369 IN CHAR8 *StoreName,
1370 IN EFI_VARSTORE_ID VarStoreId
1371 )
1372 {
1373 if (StoreName != NULL) {
1374 mVarStoreName = new CHAR8[strlen(StoreName) + 1];
1375 strcpy (mVarStoreName, StoreName);
1376 } else {
1377 mVarStoreName = NULL;
1378 }
1379 mNext = NULL;
1380 mVarStoreId = VarStoreId;
1381 mVarStoreType = EFI_VFR_VARSTORE_NAME;
1382 mStorageInfo.mNameSpace.mNameTable = new EFI_VARSTORE_ID[DEFAULT_NAME_TABLE_ITEMS];
1383 mStorageInfo.mNameSpace.mTableSize = 0;
1384 }
1385
1386 SVfrVarStorageNode::~SVfrVarStorageNode (
1387 VOID
1388 )
1389 {
1390 if (mVarStoreName != NULL) {
1391 delete mVarStoreName;
1392 }
1393
1394 if (mVarStoreType == EFI_VFR_VARSTORE_NAME) {
1395 delete mStorageInfo.mNameSpace.mNameTable;
1396 }
1397 }
1398
1399 CVfrDataStorage::CVfrDataStorage (
1400 VOID
1401 )
1402 {
1403 UINT32 Index;
1404
1405 for (Index = 0; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) {
1406 mFreeVarStoreIdBitMap[Index] = 0;
1407 }
1408
1409 // Question ID 0 is reserved.
1410 mFreeVarStoreIdBitMap[0] = 0x80000000;
1411
1412 mBufferVarStoreList = NULL;
1413 mEfiVarStoreList = NULL;
1414 mNameVarStoreList = NULL;
1415 mCurrVarStorageNode = NULL;
1416 mNewVarStorageNode = NULL;
1417 }
1418
1419 CVfrDataStorage::~CVfrDataStorage (
1420 VOID
1421 )
1422 {
1423 SVfrVarStorageNode *pNode;
1424
1425 while (mBufferVarStoreList != NULL) {
1426 pNode = mBufferVarStoreList;
1427 mBufferVarStoreList = mBufferVarStoreList->mNext;
1428 delete pNode;
1429 }
1430 while (mEfiVarStoreList != NULL) {
1431 pNode = mEfiVarStoreList;
1432 mEfiVarStoreList = mEfiVarStoreList->mNext;
1433 delete pNode;
1434 }
1435 while (mNameVarStoreList != NULL) {
1436 pNode = mNameVarStoreList;
1437 mNameVarStoreList = mNameVarStoreList->mNext;
1438 delete pNode;
1439 }
1440 if (mNewVarStorageNode != NULL) {
1441 delete mNewVarStorageNode;
1442 }
1443 }
1444
1445 EFI_VARSTORE_ID
1446 CVfrDataStorage::GetFreeVarStoreId (
1447 EFI_VFR_VARSTORE_TYPE VarType
1448 )
1449 {
1450 UINT32 Index, Mask, Offset;
1451
1452 //
1453 // Assign the different ID range for the different type VarStore to support Framework Vfr
1454 //
1455 Index = 0;
1456 if ((!VfrCompatibleMode) || (VarType == EFI_VFR_VARSTORE_BUFFER)) {
1457 Index = 0;
1458 } else if (VarType == EFI_VFR_VARSTORE_EFI) {
1459 Index = 1;
1460 } else if (VarType == EFI_VFR_VARSTORE_NAME) {
1461 Index = 2;
1462 }
1463
1464 for (; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) {
1465 if (mFreeVarStoreIdBitMap[Index] != 0xFFFFFFFF) {
1466 break;
1467 }
1468 }
1469
1470 for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
1471 if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) {
1472 mFreeVarStoreIdBitMap[Index] |= Mask;
1473 return (EFI_VARSTORE_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset);
1474 }
1475 }
1476
1477 return EFI_VARSTORE_ID_INVALID;
1478 }
1479
1480 BOOLEAN
1481 CVfrDataStorage::ChekVarStoreIdFree (
1482 IN EFI_VARSTORE_ID VarStoreId
1483 )
1484 {
1485 UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32);
1486 UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
1487
1488 return (mFreeVarStoreIdBitMap[Index] & (0x80000000 >> Offset)) == 0;
1489 }
1490
1491 VOID
1492 CVfrDataStorage::MarkVarStoreIdUsed (
1493 IN EFI_VARSTORE_ID VarStoreId
1494 )
1495 {
1496 UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32);
1497 UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
1498
1499 mFreeVarStoreIdBitMap[Index] |= (0x80000000 >> Offset);
1500 }
1501
1502 VOID
1503 CVfrDataStorage::MarkVarStoreIdUnused (
1504 IN EFI_VARSTORE_ID VarStoreId
1505 )
1506 {
1507 UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32);
1508 UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
1509
1510 mFreeVarStoreIdBitMap[Index] &= ~(0x80000000 >> Offset);
1511 }
1512
1513 EFI_VFR_RETURN_CODE
1514 CVfrDataStorage::DeclareNameVarStoreBegin (
1515 IN CHAR8 *StoreName
1516 )
1517 {
1518 SVfrVarStorageNode *pNode = NULL;
1519 EFI_VARSTORE_ID VarStoreId;
1520
1521 if (StoreName == NULL) {
1522 return VFR_RETURN_FATAL_ERROR;
1523 }
1524
1525 if (GetVarStoreId (StoreName, &VarStoreId) == VFR_RETURN_SUCCESS) {
1526 return VFR_RETURN_REDEFINED;
1527 }
1528
1529 VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME);
1530 if ((pNode = new SVfrVarStorageNode (StoreName, VarStoreId)) == NULL) {
1531 return VFR_RETURN_UNDEFINED;
1532 }
1533
1534 mNewVarStorageNode = pNode;
1535
1536 return VFR_RETURN_SUCCESS;
1537 }
1538
1539 EFI_VFR_RETURN_CODE
1540 CVfrDataStorage::NameTableAddItem (
1541 IN EFI_STRING_ID Item
1542 )
1543 {
1544 EFI_VARSTORE_ID *NewTable, *OldTable;
1545 UINT32 TableSize;
1546
1547 OldTable = mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable;
1548 TableSize = mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize;
1549
1550 if ((TableSize != 0) && ((TableSize % DEFAULT_NAME_TABLE_ITEMS) == 0)) {
1551 if ((NewTable = new EFI_VARSTORE_ID[TableSize + DEFAULT_NAME_TABLE_ITEMS]) == NULL) {
1552 return VFR_RETURN_OUT_FOR_RESOURCES;
1553 }
1554 memcpy (NewTable, OldTable, TableSize);
1555 mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable = NewTable;
1556 }
1557
1558 mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable[TableSize++] = Item;
1559 mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize = TableSize;
1560
1561 return VFR_RETURN_SUCCESS;
1562 }
1563
1564 EFI_VFR_RETURN_CODE
1565 CVfrDataStorage::DeclareNameVarStoreEnd (
1566 IN EFI_GUID *Guid
1567 )
1568 {
1569 mNewVarStorageNode->mGuid = *Guid;
1570 mNewVarStorageNode->mNext = mNameVarStoreList;
1571 mNameVarStoreList = mNewVarStorageNode;
1572
1573 mNewVarStorageNode = NULL;
1574
1575 return VFR_RETURN_SUCCESS;
1576 }
1577
1578 EFI_VFR_RETURN_CODE
1579 CVfrDataStorage::DeclareEfiVarStore (
1580 IN CHAR8 *StoreName,
1581 IN EFI_GUID *Guid,
1582 IN EFI_STRING_ID NameStrId,
1583 IN UINT32 VarSize,
1584 IN BOOLEAN Flag
1585 )
1586 {
1587 SVfrVarStorageNode *pNode;
1588 EFI_VARSTORE_ID VarStoreId;
1589
1590 if ((StoreName == NULL) || (Guid == NULL)) {
1591 return VFR_RETURN_FATAL_ERROR;
1592 }
1593
1594 if (VarSize > sizeof (UINT64)) {
1595 return VFR_RETURN_EFIVARSTORE_SIZE_ERROR;
1596 }
1597
1598 if (GetVarStoreId (StoreName, &VarStoreId, Guid) == VFR_RETURN_SUCCESS) {
1599 return VFR_RETURN_REDEFINED;
1600 }
1601
1602 VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI);
1603 if ((pNode = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, NameStrId, VarSize, Flag)) == NULL) {
1604 return VFR_RETURN_OUT_FOR_RESOURCES;
1605 }
1606
1607 pNode->mNext = mEfiVarStoreList;
1608 mEfiVarStoreList = pNode;
1609
1610 return VFR_RETURN_SUCCESS;
1611 }
1612
1613 EFI_VFR_RETURN_CODE
1614 CVfrDataStorage::DeclareBufferVarStore (
1615 IN CHAR8 *StoreName,
1616 IN EFI_GUID *Guid,
1617 IN CVfrVarDataTypeDB *DataTypeDB,
1618 IN CHAR8 *TypeName,
1619 IN EFI_VARSTORE_ID VarStoreId,
1620 IN BOOLEAN Flag
1621 )
1622 {
1623 SVfrVarStorageNode *pNew = NULL;
1624 SVfrDataType *pDataType = NULL;
1625 EFI_VARSTORE_ID TempVarStoreId;
1626
1627 if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) {
1628 return VFR_RETURN_FATAL_ERROR;
1629 }
1630
1631 if (GetVarStoreId (StoreName, &TempVarStoreId, Guid) == VFR_RETURN_SUCCESS) {
1632 return VFR_RETURN_REDEFINED;
1633 }
1634
1635 CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS);
1636
1637 if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1638 VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_BUFFER);
1639 } else {
1640 if (ChekVarStoreIdFree (VarStoreId) == FALSE) {
1641 return VFR_RETURN_VARSTOREID_REDEFINED;
1642 }
1643 MarkVarStoreIdUsed (VarStoreId);
1644 }
1645
1646 if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, Flag)) == NULL) {
1647 return VFR_RETURN_OUT_FOR_RESOURCES;
1648 }
1649
1650 pNew->mNext = mBufferVarStoreList;
1651 mBufferVarStoreList = pNew;
1652
1653 if (gCVfrBufferConfig.Register(StoreName, Guid) != 0) {
1654 return VFR_RETURN_FATAL_ERROR;
1655 }
1656
1657 return VFR_RETURN_SUCCESS;
1658 }
1659
1660 EFI_VFR_RETURN_CODE
1661 CVfrDataStorage::GetVarStoreByDataType (
1662 IN CHAR8 *DataTypeName,
1663 OUT SVfrVarStorageNode **VarNode,
1664 IN EFI_GUID *VarGuid
1665 )
1666 {
1667 SVfrVarStorageNode *pNode;
1668 SVfrVarStorageNode *MatchNode;
1669
1670 //
1671 // Framework VFR uses Data type name as varstore name, so don't need check again.
1672 //
1673 if (VfrCompatibleMode) {
1674 return VFR_RETURN_UNDEFINED;
1675 }
1676
1677 MatchNode = NULL;
1678 for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1679 if (strcmp (pNode->mStorageInfo.mDataType->mTypeName, DataTypeName) != 0) {
1680 continue;
1681 }
1682
1683 if ((VarGuid != NULL)) {
1684 if (memcmp (VarGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) {
1685 *VarNode = pNode;
1686 return VFR_RETURN_SUCCESS;
1687 }
1688 } else {
1689 if (MatchNode == NULL) {
1690 MatchNode = pNode;
1691 } else {
1692 //
1693 // More than one varstores referred the same data structures.
1694 //
1695 return VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR;
1696 }
1697 }
1698 }
1699
1700 if (MatchNode == NULL) {
1701 return VFR_RETURN_UNDEFINED;
1702 }
1703
1704 *VarNode = MatchNode;
1705 return VFR_RETURN_SUCCESS;
1706 }
1707
1708 EFI_VARSTORE_ID
1709 CVfrDataStorage::CheckGuidField (
1710 IN SVfrVarStorageNode *pNode,
1711 IN EFI_GUID *StoreGuid,
1712 IN BOOLEAN *HasFoundOne,
1713 OUT EFI_VFR_RETURN_CODE *ReturnCode
1714 )
1715 {
1716 if (StoreGuid != NULL) {
1717 //
1718 // If has guid info, compare the guid filed.
1719 //
1720 if (memcmp (StoreGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) {
1721 //
1722 // Both name and guid are same, this this varstore.
1723 //
1724 mCurrVarStorageNode = pNode;
1725 *ReturnCode = VFR_RETURN_SUCCESS;
1726 return TRUE;
1727 }
1728 } else {
1729 //
1730 // Not has Guid field, check whether this name is the only one.
1731 //
1732 if (*HasFoundOne) {
1733 //
1734 // The name has conflict, return name redefined.
1735 //
1736 *ReturnCode = VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR;
1737 return TRUE;
1738 }
1739
1740 *HasFoundOne = TRUE;
1741 mCurrVarStorageNode = pNode;
1742 }
1743
1744 return FALSE;
1745 }
1746
1747 /**
1748 Base on the input store name and guid to find the varstore id.
1749
1750 If both name and guid are inputed, base on the name and guid to
1751 found the varstore. If only name inputed, base on the name to
1752 found the varstore and go on to check whether more than one varstore
1753 has the same name. If only has found one varstore, return this
1754 varstore; if more than one varstore has same name, return varstore
1755 name redefined error. If no varstore found by varstore name, call
1756 function GetVarStoreByDataType and use inputed varstore name as
1757 data type name to search.
1758 **/
1759 EFI_VFR_RETURN_CODE
1760 CVfrDataStorage::GetVarStoreId (
1761 IN CHAR8 *StoreName,
1762 OUT EFI_VARSTORE_ID *VarStoreId,
1763 IN EFI_GUID *StoreGuid
1764 )
1765 {
1766 EFI_VFR_RETURN_CODE ReturnCode;
1767 SVfrVarStorageNode *pNode;
1768 BOOLEAN HasFoundOne = FALSE;
1769
1770 mCurrVarStorageNode = NULL;
1771
1772 for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1773 if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
1774 if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
1775 *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1776 return ReturnCode;
1777 }
1778 }
1779 }
1780
1781 for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1782 if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
1783 if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
1784 *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1785 return ReturnCode;
1786 }
1787 }
1788 }
1789
1790 for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1791 if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
1792 if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
1793 *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1794 return ReturnCode;
1795 }
1796 }
1797 }
1798
1799 if (HasFoundOne) {
1800 *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1801 return VFR_RETURN_SUCCESS;
1802 }
1803
1804 *VarStoreId = EFI_VARSTORE_ID_INVALID;
1805
1806 //
1807 // Assume that Data strucutre name is used as StoreName, and check again.
1808 //
1809 ReturnCode = GetVarStoreByDataType (StoreName, &pNode, StoreGuid);
1810 if (pNode != NULL) {
1811 mCurrVarStorageNode = pNode;
1812 *VarStoreId = pNode->mVarStoreId;
1813 }
1814
1815 return ReturnCode;
1816 }
1817
1818 EFI_VFR_RETURN_CODE
1819 CVfrDataStorage::GetBufferVarStoreDataTypeName (
1820 IN EFI_VARSTORE_ID VarStoreId,
1821 OUT CHAR8 **DataTypeName
1822 )
1823 {
1824 SVfrVarStorageNode *pNode;
1825
1826 if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1827 return VFR_RETURN_FATAL_ERROR;
1828 }
1829
1830 for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1831 if (pNode->mVarStoreId == VarStoreId) {
1832 *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName;
1833 return VFR_RETURN_SUCCESS;
1834 }
1835 }
1836
1837 return VFR_RETURN_UNDEFINED;
1838 }
1839
1840 EFI_VFR_VARSTORE_TYPE
1841 CVfrDataStorage::GetVarStoreType (
1842 IN EFI_VARSTORE_ID VarStoreId
1843 )
1844 {
1845 SVfrVarStorageNode *pNode;
1846 EFI_VFR_VARSTORE_TYPE VarStoreType;
1847
1848 VarStoreType = EFI_VFR_VARSTORE_INVALID;
1849
1850 if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1851 return VarStoreType;
1852 }
1853
1854 for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1855 if (pNode->mVarStoreId == VarStoreId) {
1856 VarStoreType = pNode->mVarStoreType;
1857 return VarStoreType;
1858 }
1859 }
1860
1861 for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1862 if (pNode->mVarStoreId == VarStoreId) {
1863 VarStoreType = pNode->mVarStoreType;
1864 return VarStoreType;
1865 }
1866 }
1867
1868 for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1869 if (pNode->mVarStoreId == VarStoreId) {
1870 VarStoreType = pNode->mVarStoreType;
1871 return VarStoreType;
1872 }
1873 }
1874
1875 return VarStoreType;
1876 }
1877
1878 EFI_GUID *
1879 CVfrDataStorage::GetVarStoreGuid (
1880 IN EFI_VARSTORE_ID VarStoreId
1881 )
1882 {
1883 SVfrVarStorageNode *pNode;
1884 EFI_GUID *VarGuid;
1885
1886 VarGuid = NULL;
1887
1888 if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1889 return VarGuid;
1890 }
1891
1892 for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1893 if (pNode->mVarStoreId == VarStoreId) {
1894 VarGuid = &pNode->mGuid;
1895 return VarGuid;
1896 }
1897 }
1898
1899 for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1900 if (pNode->mVarStoreId == VarStoreId) {
1901 VarGuid = &pNode->mGuid;
1902 return VarGuid;
1903 }
1904 }
1905
1906 for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1907 if (pNode->mVarStoreId == VarStoreId) {
1908 VarGuid = &pNode->mGuid;
1909 return VarGuid;
1910 }
1911 }
1912
1913 return VarGuid;
1914 }
1915
1916 EFI_VFR_RETURN_CODE
1917 CVfrDataStorage::GetVarStoreName (
1918 IN EFI_VARSTORE_ID VarStoreId,
1919 OUT CHAR8 **VarStoreName
1920 )
1921 {
1922 SVfrVarStorageNode *pNode;
1923
1924 if (VarStoreName == NULL) {
1925 return VFR_RETURN_FATAL_ERROR;
1926 }
1927
1928 for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1929 if (pNode->mVarStoreId == VarStoreId) {
1930 *VarStoreName = pNode->mVarStoreName;
1931 return VFR_RETURN_SUCCESS;
1932 }
1933 }
1934
1935 for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1936 if (pNode->mVarStoreId == VarStoreId) {
1937 *VarStoreName = pNode->mVarStoreName;
1938 return VFR_RETURN_SUCCESS;
1939 }
1940 }
1941
1942 for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1943 if (pNode->mVarStoreId == VarStoreId) {
1944 *VarStoreName = pNode->mVarStoreName;
1945 return VFR_RETURN_SUCCESS;
1946 }
1947 }
1948
1949 *VarStoreName = NULL;
1950 return VFR_RETURN_UNDEFINED;
1951 }
1952
1953 EFI_VFR_RETURN_CODE
1954 CVfrDataStorage::GetEfiVarStoreInfo (
1955 IN OUT EFI_VARSTORE_INFO *Info
1956 )
1957 {
1958 if (Info == NULL) {
1959 return VFR_RETURN_FATAL_ERROR;
1960 }
1961
1962 if (mCurrVarStorageNode == NULL) {
1963 return VFR_RETURN_GET_EFIVARSTORE_ERROR;
1964 }
1965
1966 Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarName;
1967 Info->mVarTotalSize = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarSize;
1968 switch (Info->mVarTotalSize) {
1969 case 1:
1970 Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
1971 break;
1972 case 2:
1973 Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_16;
1974 break;
1975 case 4:
1976 Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_32;
1977 break;
1978 case 8:
1979 Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_64;
1980 break;
1981 default :
1982 return VFR_RETURN_FATAL_ERROR;
1983 }
1984
1985 return VFR_RETURN_SUCCESS;
1986 }
1987
1988 EFI_VFR_RETURN_CODE
1989 CVfrDataStorage::GetNameVarStoreInfo (
1990 OUT EFI_VARSTORE_INFO *Info,
1991 IN UINT32 Index
1992 )
1993 {
1994 if (Info == NULL) {
1995 return VFR_RETURN_FATAL_ERROR;
1996 }
1997
1998 if (mCurrVarStorageNode == NULL) {
1999 return VFR_RETURN_GET_NVVARSTORE_ERROR;
2000 }
2001
2002 //
2003 // Framework Vfr file Index is from 1, but Uefi Vfr file Index is from 0.
2004 //
2005 if (VfrCompatibleMode) {
2006 if (Index == 0) {
2007 return VFR_RETURN_ERROR_ARRARY_NUM;
2008 }
2009 Index --;
2010 }
2011
2012 Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mNameSpace.mNameTable[Index];
2013
2014 return VFR_RETURN_SUCCESS;
2015 }
2016
2017 SVfrDefaultStoreNode::SVfrDefaultStoreNode (
2018 IN EFI_IFR_DEFAULTSTORE *ObjBinAddr,
2019 IN CHAR8 *RefName,
2020 IN EFI_STRING_ID DefaultStoreNameId,
2021 IN UINT16 DefaultId
2022 )
2023 {
2024 mObjBinAddr = ObjBinAddr;
2025
2026 if (RefName != NULL) {
2027 mRefName = new CHAR8[strlen (RefName) + 1];
2028 strcpy (mRefName, RefName);
2029 } else {
2030 mRefName = NULL;
2031 }
2032
2033 mNext = NULL;
2034 mDefaultId = DefaultId;
2035 mDefaultStoreNameId = DefaultStoreNameId;
2036 }
2037
2038 SVfrDefaultStoreNode::~SVfrDefaultStoreNode (
2039 VOID
2040 )
2041 {
2042 if (mRefName != NULL) {
2043 delete mRefName;
2044 }
2045 }
2046
2047 CVfrDefaultStore::CVfrDefaultStore (
2048 VOID
2049 )
2050 {
2051 mDefaultStoreList = NULL;
2052 }
2053
2054 CVfrDefaultStore::~CVfrDefaultStore (
2055 VOID
2056 )
2057 {
2058 SVfrDefaultStoreNode *pTmp = NULL;
2059
2060 while (mDefaultStoreList != NULL) {
2061 pTmp = mDefaultStoreList;
2062 mDefaultStoreList = mDefaultStoreList->mNext;
2063 delete pTmp;
2064 }
2065 }
2066
2067 EFI_VFR_RETURN_CODE
2068 CVfrDefaultStore::RegisterDefaultStore (
2069 IN CHAR8 *ObjBinAddr,
2070 IN CHAR8 *RefName,
2071 IN EFI_STRING_ID DefaultStoreNameId,
2072 IN UINT16 DefaultId
2073 )
2074 {
2075 SVfrDefaultStoreNode *pNode = NULL;
2076
2077 if (RefName == NULL) {
2078 return VFR_RETURN_FATAL_ERROR;
2079 }
2080
2081 for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2082 if (strcmp (pNode->mRefName, RefName) == 0) {
2083 return VFR_RETURN_REDEFINED;
2084 }
2085 }
2086
2087 if ((pNode = new SVfrDefaultStoreNode ((EFI_IFR_DEFAULTSTORE *)ObjBinAddr, RefName, DefaultStoreNameId, DefaultId)) == NULL) {
2088 return VFR_RETURN_OUT_FOR_RESOURCES;
2089 }
2090
2091 pNode->mNext = mDefaultStoreList;
2092 mDefaultStoreList = pNode;
2093
2094 return VFR_RETURN_SUCCESS;
2095 }
2096
2097 /*
2098 * assign new reference name or new default store name id only if
2099 * the original is invalid
2100 */
2101 EFI_VFR_RETURN_CODE
2102 CVfrDefaultStore::ReRegisterDefaultStoreById (
2103 IN UINT16 DefaultId,
2104 IN CHAR8 *RefName,
2105 IN EFI_STRING_ID DefaultStoreNameId
2106 )
2107 {
2108 SVfrDefaultStoreNode *pNode = NULL;
2109
2110 for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2111 if (pNode->mDefaultId == DefaultId) {
2112 break;
2113 }
2114 }
2115
2116 if (pNode == NULL) {
2117 return VFR_RETURN_UNDEFINED;
2118 } else {
2119 if (pNode->mDefaultStoreNameId == EFI_STRING_ID_INVALID) {
2120 pNode->mDefaultStoreNameId = DefaultStoreNameId;
2121 if (pNode->mObjBinAddr != NULL) {
2122 pNode->mObjBinAddr->DefaultName = DefaultStoreNameId;
2123 }
2124 } else {
2125 return VFR_RETURN_REDEFINED;
2126 }
2127
2128 if (RefName != NULL) {
2129 delete pNode->mRefName;
2130 pNode->mRefName = new CHAR8[strlen (RefName) + 1];
2131 if (pNode->mRefName != NULL) {
2132 strcpy (pNode->mRefName, RefName);
2133 }
2134 }
2135 }
2136
2137 return VFR_RETURN_SUCCESS;
2138 }
2139
2140 BOOLEAN
2141 CVfrDefaultStore::DefaultIdRegistered (
2142 IN UINT16 DefaultId
2143 )
2144 {
2145 SVfrDefaultStoreNode *pNode = NULL;
2146
2147 for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2148 if (pNode->mDefaultId == DefaultId) {
2149 return TRUE;
2150 }
2151 }
2152
2153 return FALSE;
2154 }
2155
2156 EFI_VFR_RETURN_CODE
2157 CVfrDefaultStore::GetDefaultId (
2158 IN CHAR8 *RefName,
2159 OUT UINT16 *DefaultId
2160 )
2161 {
2162 SVfrDefaultStoreNode *pTmp = NULL;
2163
2164 if (DefaultId == NULL) {
2165 return VFR_RETURN_FATAL_ERROR;
2166 }
2167
2168 for (pTmp = mDefaultStoreList; pTmp != NULL; pTmp = pTmp->mNext) {
2169 if (strcmp (pTmp->mRefName, RefName) == 0) {
2170 *DefaultId = pTmp->mDefaultId;
2171 return VFR_RETURN_SUCCESS;
2172 }
2173 }
2174
2175 return VFR_RETURN_UNDEFINED;
2176 }
2177
2178 EFI_VFR_RETURN_CODE
2179 CVfrDefaultStore::BufferVarStoreAltConfigAdd (
2180 IN EFI_VARSTORE_ID DefaultId,
2181 IN EFI_VARSTORE_INFO &Info,
2182 IN CHAR8 *VarStoreName,
2183 IN EFI_GUID *VarStoreGuid,
2184 IN UINT8 Type,
2185 IN EFI_IFR_TYPE_VALUE Value
2186 )
2187 {
2188 SVfrDefaultStoreNode *pNode = NULL;
2189 CHAR8 NewAltCfg[2 * 2 * sizeof (UINT16) + 1] = {0,};
2190 INTN Returnvalue = 0;
2191
2192 if (VarStoreName == NULL) {
2193 return VFR_RETURN_FATAL_ERROR;
2194 }
2195
2196 for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2197 if (pNode->mDefaultId == DefaultId) {
2198 break;
2199 }
2200 }
2201
2202 if (pNode == NULL) {
2203 return VFR_RETURN_UNDEFINED;
2204 }
2205
2206 gCVfrBufferConfig.Open ();
2207
2208 sprintf (NewAltCfg, "%04x", pNode->mDefaultId);
2209 if ((Returnvalue = gCVfrBufferConfig.Select(VarStoreName, VarStoreGuid)) == 0) {
2210 if ((Returnvalue = gCVfrBufferConfig.Write ('a', VarStoreName, VarStoreGuid, NewAltCfg, Type, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value)) != 0) {
2211 goto WriteError;
2212 }
2213 }
2214
2215 gCVfrBufferConfig.Close ();
2216
2217 return VFR_RETURN_SUCCESS;
2218
2219 WriteError:
2220 gCVfrBufferConfig.Close ();
2221 return (EFI_VFR_RETURN_CODE)Returnvalue;
2222 }
2223
2224 SVfrRuleNode::SVfrRuleNode (
2225 IN CHAR8 *RuleName,
2226 IN UINT8 RuleId
2227 )
2228 {
2229 if (RuleName != NULL) {
2230 mRuleName = new CHAR8[strlen (RuleName) + 1];
2231 strcpy (mRuleName, RuleName);
2232 } else {
2233 mRuleName = NULL;
2234 }
2235
2236 mNext = NULL;
2237 mRuleId = RuleId;
2238 }
2239
2240 SVfrRuleNode::~SVfrRuleNode (
2241 VOID
2242 )
2243 {
2244 if (mRuleName != NULL) {
2245 delete mRuleName;
2246 }
2247 }
2248
2249 CVfrRulesDB::CVfrRulesDB ()
2250 {
2251 mRuleList = NULL;
2252 mFreeRuleId = EFI_VARSTORE_ID_START;
2253 }
2254
2255 CVfrRulesDB::~CVfrRulesDB ()
2256 {
2257 SVfrRuleNode *pNode;
2258
2259 while(mRuleList != NULL) {
2260 pNode = mRuleList;
2261 mRuleList = mRuleList->mNext;
2262 delete pNode;
2263 }
2264 }
2265
2266 VOID
2267 CVfrRulesDB::RegisterRule (
2268 IN CHAR8 *RuleName
2269 )
2270 {
2271 SVfrRuleNode *pNew;
2272
2273 if (RuleName == NULL) {
2274 return ;
2275 }
2276
2277 if ((pNew = new SVfrRuleNode (RuleName, mFreeRuleId)) == NULL) {
2278 return ;
2279 }
2280
2281 mFreeRuleId++;
2282
2283 pNew->mNext = mRuleList;
2284 mRuleList = pNew;
2285 }
2286
2287 UINT8
2288 CVfrRulesDB::GetRuleId (
2289 IN CHAR8 *RuleName
2290 )
2291 {
2292 SVfrRuleNode *pNode;
2293
2294 if (RuleName == NULL) {
2295 return EFI_RULE_ID_INVALID;
2296 }
2297
2298 for (pNode = mRuleList; pNode != NULL; pNode = pNode->mNext) {
2299 if (strcmp (pNode->mRuleName, RuleName) == 0) {
2300 return pNode->mRuleId;
2301 }
2302 }
2303
2304 return EFI_RULE_ID_INVALID;
2305 }
2306
2307 CVfrRulesDB gCVfrRulesDB;
2308
2309 EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
2310 VOID
2311 )
2312 {
2313 mVarStoreId = EFI_VARSTORE_ID_INVALID;
2314 mInfo.mVarName = EFI_STRING_ID_INVALID;
2315 mInfo.mVarOffset = EFI_VAROFFSET_INVALID;
2316 mVarType = EFI_IFR_TYPE_OTHER;
2317 mVarTotalSize = 0;
2318 }
2319
2320 EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
2321 IN EFI_VARSTORE_INFO &Info
2322 )
2323 {
2324 mVarStoreId = Info.mVarStoreId;
2325 mInfo.mVarName = Info.mInfo.mVarName;
2326 mInfo.mVarOffset = Info.mInfo.mVarOffset;
2327 mVarType = Info.mVarType;
2328 mVarTotalSize = Info.mVarTotalSize;
2329 }
2330
2331 BOOLEAN
2332 EFI_VARSTORE_INFO::operator == (
2333 IN EFI_VARSTORE_INFO *Info
2334 )
2335 {
2336 if ((mVarStoreId == Info->mVarStoreId) &&
2337 (mInfo.mVarName == Info->mInfo.mVarName) &&
2338 (mInfo.mVarOffset == Info->mInfo.mVarOffset) &&
2339 (mVarType == Info->mVarType) &&
2340 (mVarTotalSize == Info->mVarTotalSize)) {
2341 return TRUE;
2342 }
2343
2344 return FALSE;
2345 }
2346
2347 static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo;
2348
2349 EFI_QUESTION_ID
2350 CVfrQuestionDB::GetFreeQuestionId (
2351 VOID
2352 )
2353 {
2354 UINT32 Index, Mask, Offset;
2355
2356 for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
2357 if (mFreeQIdBitMap[Index] != 0xFFFFFFFF) {
2358 break;
2359 }
2360 }
2361
2362 for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
2363 if ((mFreeQIdBitMap[Index] & Mask) == 0) {
2364 mFreeQIdBitMap[Index] |= Mask;
2365 return (EFI_QUESTION_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset);
2366 }
2367 }
2368
2369 return EFI_QUESTION_ID_INVALID;
2370 }
2371
2372 BOOLEAN
2373 CVfrQuestionDB::ChekQuestionIdFree (
2374 IN EFI_QUESTION_ID QId
2375 )
2376 {
2377 UINT32 Index = (QId / EFI_BITS_PER_UINT32);
2378 UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
2379
2380 return (mFreeQIdBitMap[Index] & (0x80000000 >> Offset)) == 0;
2381 }
2382
2383 VOID
2384 CVfrQuestionDB::MarkQuestionIdUsed (
2385 IN EFI_QUESTION_ID QId
2386 )
2387 {
2388 UINT32 Index = (QId / EFI_BITS_PER_UINT32);
2389 UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
2390
2391 mFreeQIdBitMap[Index] |= (0x80000000 >> Offset);
2392 }
2393
2394 VOID
2395 CVfrQuestionDB::MarkQuestionIdUnused (
2396 IN EFI_QUESTION_ID QId
2397 )
2398 {
2399 UINT32 Index = (QId / EFI_BITS_PER_UINT32);
2400 UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
2401
2402 mFreeQIdBitMap[Index] &= ~(0x80000000 >> Offset);
2403 }
2404
2405 SVfrQuestionNode::SVfrQuestionNode (
2406 IN CHAR8 *Name,
2407 IN CHAR8 *VarIdStr,
2408 IN UINT32 BitMask
2409 )
2410 {
2411 mName = NULL;
2412 mVarIdStr = NULL;
2413 mQuestionId = EFI_QUESTION_ID_INVALID;
2414 mBitMask = BitMask;
2415 mNext = NULL;
2416 mQtype = QUESTION_NORMAL;
2417
2418 if (Name == NULL) {
2419 mName = new CHAR8[strlen ("$DEFAULT") + 1];
2420 strcpy (mName, "$DEFAULT");
2421 } else {
2422 mName = new CHAR8[strlen (Name) + 1];
2423 strcpy (mName, Name);
2424 }
2425
2426 if (VarIdStr != NULL) {
2427 mVarIdStr = new CHAR8[strlen (VarIdStr) + 1];
2428 strcpy (mVarIdStr, VarIdStr);
2429 } else {
2430 mVarIdStr = new CHAR8[strlen ("$") + 1];
2431 strcpy (mVarIdStr, "$");
2432 }
2433 }
2434
2435 SVfrQuestionNode::~SVfrQuestionNode (
2436 VOID
2437 )
2438 {
2439 if (mName != NULL) {
2440 delete mName;
2441 }
2442
2443 if (mVarIdStr != NULL) {
2444 delete mVarIdStr;
2445 }
2446 }
2447
2448 CVfrQuestionDB::CVfrQuestionDB ()
2449 {
2450 UINT32 Index;
2451
2452 for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
2453 mFreeQIdBitMap[Index] = 0;
2454 }
2455
2456 // Question ID 0 is reserved.
2457 mFreeQIdBitMap[0] = 0x80000000;
2458 mQuestionList = NULL;
2459 }
2460
2461 CVfrQuestionDB::~CVfrQuestionDB ()
2462 {
2463 SVfrQuestionNode *pNode;
2464
2465 while (mQuestionList != NULL) {
2466 pNode = mQuestionList;
2467 mQuestionList = mQuestionList->mNext;
2468 delete pNode;
2469 }
2470 }
2471
2472 //
2473 // Reset to init state
2474 //
2475 VOID
2476 CVfrQuestionDB::ResetInit(
2477 IN VOID
2478 )
2479 {
2480 UINT32 Index;
2481 SVfrQuestionNode *pNode;
2482
2483 while (mQuestionList != NULL) {
2484 pNode = mQuestionList;
2485 mQuestionList = mQuestionList->mNext;
2486 delete pNode;
2487 }
2488
2489 for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
2490 mFreeQIdBitMap[Index] = 0;
2491 }
2492
2493 // Question ID 0 is reserved.
2494 mFreeQIdBitMap[0] = 0x80000000;
2495 mQuestionList = NULL;
2496 }
2497
2498 VOID
2499 CVfrQuestionDB::PrintAllQuestion (
2500 VOID
2501 )
2502 {
2503 SVfrQuestionNode *pNode = NULL;
2504
2505 for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
2506 printf ("Question VarId is %s and QuesitonId is 0x%x\n", pNode->mVarIdStr, pNode->mQuestionId);
2507 }
2508 }
2509
2510 EFI_VFR_RETURN_CODE
2511 CVfrQuestionDB::RegisterQuestion (
2512 IN CHAR8 *Name,
2513 IN CHAR8 *VarIdStr,
2514 IN OUT EFI_QUESTION_ID &QuestionId
2515 )
2516 {
2517 SVfrQuestionNode *pNode = NULL;
2518
2519 if ((Name != NULL) && (FindQuestion(Name) == VFR_RETURN_SUCCESS)) {
2520 return VFR_RETURN_REDEFINED;
2521 }
2522
2523 if ((pNode = new SVfrQuestionNode (Name, VarIdStr)) == NULL) {
2524 return VFR_RETURN_OUT_FOR_RESOURCES;
2525 }
2526
2527 if (QuestionId == EFI_QUESTION_ID_INVALID) {
2528 QuestionId = GetFreeQuestionId ();
2529 } else {
2530 //
2531 // For Framework Vfr, don't check question ID conflict.
2532 //
2533 if (!VfrCompatibleMode && ChekQuestionIdFree (QuestionId) == FALSE) {
2534 delete pNode;
2535 return VFR_RETURN_QUESTIONID_REDEFINED;
2536 }
2537 MarkQuestionIdUsed (QuestionId);
2538 }
2539 pNode->mQuestionId = QuestionId;
2540
2541 pNode->mNext = mQuestionList;
2542 mQuestionList = pNode;
2543
2544 gCFormPkg.DoPendingAssign (VarIdStr, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2545
2546 return VFR_RETURN_SUCCESS;
2547 }
2548
2549 VOID
2550 CVfrQuestionDB::RegisterOldDateQuestion (
2551 IN CHAR8 *YearVarId,
2552 IN CHAR8 *MonthVarId,
2553 IN CHAR8 *DayVarId,
2554 IN OUT EFI_QUESTION_ID &QuestionId
2555 )
2556 {
2557 SVfrQuestionNode *pNode[3] = {NULL, };
2558 UINT32 Index;
2559
2560 if ((YearVarId == NULL) || (MonthVarId == NULL) || (DayVarId == NULL)) {
2561 return;
2562 }
2563
2564 if ((pNode[0] = new SVfrQuestionNode (NULL, YearVarId, DATE_YEAR_BITMASK)) == NULL) {
2565 goto Err;
2566 }
2567 if ((pNode[1] = new SVfrQuestionNode (NULL, MonthVarId, DATE_MONTH_BITMASK)) == NULL) {
2568 goto Err;
2569 }
2570 if ((pNode[2] = new SVfrQuestionNode (NULL, DayVarId, DATE_DAY_BITMASK)) == NULL) {
2571 goto Err;
2572 }
2573
2574 if (QuestionId == EFI_QUESTION_ID_INVALID) {
2575 QuestionId = GetFreeQuestionId ();
2576 } else {
2577 if (ChekQuestionIdFree (QuestionId) == FALSE) {
2578 goto Err;
2579 }
2580 MarkQuestionIdUsed (QuestionId);
2581 }
2582
2583 pNode[0]->mQuestionId = QuestionId;
2584 pNode[1]->mQuestionId = QuestionId;
2585 pNode[2]->mQuestionId = QuestionId;
2586 pNode[0]->mQtype = QUESTION_DATE;
2587 pNode[1]->mQtype = QUESTION_DATE;
2588 pNode[2]->mQtype = QUESTION_DATE;
2589 pNode[0]->mNext = pNode[1];
2590 pNode[1]->mNext = pNode[2];
2591 pNode[2]->mNext = mQuestionList;
2592 mQuestionList = pNode[0];
2593
2594 gCFormPkg.DoPendingAssign (YearVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2595 gCFormPkg.DoPendingAssign (MonthVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2596 gCFormPkg.DoPendingAssign (DayVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2597
2598 return;
2599
2600 Err:
2601 for (Index = 0; Index < 3; Index++) {
2602 if (pNode[Index] != NULL) {
2603 delete pNode[Index];
2604 }
2605 }
2606 QuestionId = EFI_QUESTION_ID_INVALID;
2607 }
2608
2609 VOID
2610 CVfrQuestionDB::RegisterNewDateQuestion (
2611 IN CHAR8 *Name,
2612 IN CHAR8 *BaseVarId,
2613 IN OUT EFI_QUESTION_ID &QuestionId
2614 )
2615 {
2616 SVfrQuestionNode *pNode[3] = {NULL, };
2617 UINT32 Len;
2618 CHAR8 *VarIdStr[3] = {NULL, };
2619 CHAR8 Index;
2620
2621 if (BaseVarId == NULL && Name == NULL) {
2622 return;
2623 }
2624
2625 if (BaseVarId != NULL) {
2626 Len = strlen (BaseVarId);
2627
2628 VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1];
2629 if (VarIdStr[0] != NULL) {
2630 strcpy (VarIdStr[0], BaseVarId);
2631 strcat (VarIdStr[0], ".Year");
2632 }
2633 VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1];
2634 if (VarIdStr[1] != NULL) {
2635 strcpy (VarIdStr[1], BaseVarId);
2636 strcat (VarIdStr[1], ".Month");
2637 }
2638 VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1];
2639 if (VarIdStr[2] != NULL) {
2640 strcpy (VarIdStr[2], BaseVarId);
2641 strcat (VarIdStr[2], ".Day");
2642 }
2643 } else {
2644 Len = strlen (Name);
2645
2646 VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1];
2647 if (VarIdStr[0] != NULL) {
2648 strcpy (VarIdStr[0], Name);
2649 strcat (VarIdStr[0], ".Year");
2650 }
2651 VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1];
2652 if (VarIdStr[1] != NULL) {
2653 strcpy (VarIdStr[1], Name);
2654 strcat (VarIdStr[1], ".Month");
2655 }
2656 VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1];
2657 if (VarIdStr[2] != NULL) {
2658 strcpy (VarIdStr[2], Name);
2659 strcat (VarIdStr[2], ".Day");
2660 }
2661 }
2662
2663 if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], DATE_YEAR_BITMASK)) == NULL) {
2664 goto Err;
2665 }
2666 if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], DATE_MONTH_BITMASK)) == NULL) {
2667 goto Err;
2668 }
2669 if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], DATE_DAY_BITMASK)) == NULL) {
2670 goto Err;
2671 }
2672
2673 if (QuestionId == EFI_QUESTION_ID_INVALID) {
2674 QuestionId = GetFreeQuestionId ();
2675 } else {
2676 if (ChekQuestionIdFree (QuestionId) == FALSE) {
2677 goto Err;
2678 }
2679 MarkQuestionIdUsed (QuestionId);
2680 }
2681
2682 pNode[0]->mQuestionId = QuestionId;
2683 pNode[1]->mQuestionId = QuestionId;
2684 pNode[2]->mQuestionId = QuestionId;
2685 pNode[0]->mQtype = QUESTION_DATE;
2686 pNode[1]->mQtype = QUESTION_DATE;
2687 pNode[2]->mQtype = QUESTION_DATE;
2688 pNode[0]->mNext = pNode[1];
2689 pNode[1]->mNext = pNode[2];
2690 pNode[2]->mNext = mQuestionList;
2691 mQuestionList = pNode[0];
2692
2693 for (Index = 0; Index < 3; Index++) {
2694 if (VarIdStr[Index] != NULL) {
2695 delete VarIdStr[Index];
2696 }
2697 }
2698
2699 gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2700 gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2701 gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2702
2703 return;
2704
2705 Err:
2706 for (Index = 0; Index < 3; Index++) {
2707 if (pNode[Index] != NULL) {
2708 delete pNode[Index];
2709 }
2710
2711 if (VarIdStr[Index] != NULL) {
2712 delete VarIdStr[Index];
2713 }
2714 }
2715 }
2716
2717 VOID
2718 CVfrQuestionDB::RegisterOldTimeQuestion (
2719 IN CHAR8 *HourVarId,
2720 IN CHAR8 *MinuteVarId,
2721 IN CHAR8 *SecondVarId,
2722 IN OUT EFI_QUESTION_ID &QuestionId
2723 )
2724 {
2725 SVfrQuestionNode *pNode[3] = {NULL, };
2726 UINT32 Index;
2727
2728 if ((HourVarId == NULL) || (MinuteVarId == NULL) || (SecondVarId == NULL)) {
2729 return;
2730 }
2731
2732 if ((pNode[0] = new SVfrQuestionNode (NULL, HourVarId, TIME_HOUR_BITMASK)) == NULL) {
2733 goto Err;
2734 }
2735 if ((pNode[1] = new SVfrQuestionNode (NULL, MinuteVarId, TIME_MINUTE_BITMASK)) == NULL) {
2736 goto Err;
2737 }
2738 if ((pNode[2] = new SVfrQuestionNode (NULL, SecondVarId, TIME_SECOND_BITMASK)) == NULL) {
2739 goto Err;
2740 }
2741
2742 if (QuestionId == EFI_QUESTION_ID_INVALID) {
2743 QuestionId = GetFreeQuestionId ();
2744 } else {
2745 if (ChekQuestionIdFree (QuestionId) == FALSE) {
2746 goto Err;
2747 }
2748 MarkQuestionIdUsed (QuestionId);
2749 }
2750
2751 pNode[0]->mQuestionId = QuestionId;
2752 pNode[1]->mQuestionId = QuestionId;
2753 pNode[2]->mQuestionId = QuestionId;
2754 pNode[0]->mQtype = QUESTION_TIME;
2755 pNode[1]->mQtype = QUESTION_TIME;
2756 pNode[2]->mQtype = QUESTION_TIME;
2757 pNode[0]->mNext = pNode[1];
2758 pNode[1]->mNext = pNode[2];
2759 pNode[2]->mNext = mQuestionList;
2760 mQuestionList = pNode[0];
2761
2762 gCFormPkg.DoPendingAssign (HourVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2763 gCFormPkg.DoPendingAssign (MinuteVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2764 gCFormPkg.DoPendingAssign (SecondVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2765
2766 return;
2767
2768 Err:
2769 for (Index = 0; Index < 3; Index++) {
2770 if (pNode[Index] != NULL) {
2771 delete pNode[Index];
2772 }
2773 }
2774 QuestionId = EFI_QUESTION_ID_INVALID;
2775 }
2776
2777 VOID
2778 CVfrQuestionDB::RegisterNewTimeQuestion (
2779 IN CHAR8 *Name,
2780 IN CHAR8 *BaseVarId,
2781 IN OUT EFI_QUESTION_ID &QuestionId
2782 )
2783 {
2784 SVfrQuestionNode *pNode[3] = {NULL, };
2785 UINT32 Len;
2786 CHAR8 *VarIdStr[3] = {NULL, };
2787 CHAR8 Index;
2788
2789 if (BaseVarId == NULL && Name == NULL) {
2790 return;
2791 }
2792
2793 if (BaseVarId != NULL) {
2794 Len = strlen (BaseVarId);
2795
2796 VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1];
2797 if (VarIdStr[0] != NULL) {
2798 strcpy (VarIdStr[0], BaseVarId);
2799 strcat (VarIdStr[0], ".Hour");
2800 }
2801 VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1];
2802 if (VarIdStr[1] != NULL) {
2803 strcpy (VarIdStr[1], BaseVarId);
2804 strcat (VarIdStr[1], ".Minute");
2805 }
2806 VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1];
2807 if (VarIdStr[2] != NULL) {
2808 strcpy (VarIdStr[2], BaseVarId);
2809 strcat (VarIdStr[2], ".Second");
2810 }
2811 } else {
2812 Len = strlen (Name);
2813
2814 VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1];
2815 if (VarIdStr[0] != NULL) {
2816 strcpy (VarIdStr[0], Name);
2817 strcat (VarIdStr[0], ".Hour");
2818 }
2819 VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1];
2820 if (VarIdStr[1] != NULL) {
2821 strcpy (VarIdStr[1], Name);
2822 strcat (VarIdStr[1], ".Minute");
2823 }
2824 VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1];
2825 if (VarIdStr[2] != NULL) {
2826 strcpy (VarIdStr[2], Name);
2827 strcat (VarIdStr[2], ".Second");
2828 }
2829 }
2830
2831 if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], TIME_HOUR_BITMASK)) == NULL) {
2832 goto Err;
2833 }
2834 if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], TIME_MINUTE_BITMASK)) == NULL) {
2835 goto Err;
2836 }
2837 if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], TIME_SECOND_BITMASK)) == NULL) {
2838 goto Err;
2839 }
2840
2841 if (QuestionId == EFI_QUESTION_ID_INVALID) {
2842 QuestionId = GetFreeQuestionId ();
2843 } else {
2844 if (ChekQuestionIdFree (QuestionId) == FALSE) {
2845 goto Err;
2846 }
2847 MarkQuestionIdUsed (QuestionId);
2848 }
2849
2850 pNode[0]->mQuestionId = QuestionId;
2851 pNode[1]->mQuestionId = QuestionId;
2852 pNode[2]->mQuestionId = QuestionId;
2853 pNode[0]->mQtype = QUESTION_TIME;
2854 pNode[1]->mQtype = QUESTION_TIME;
2855 pNode[2]->mQtype = QUESTION_TIME;
2856 pNode[0]->mNext = pNode[1];
2857 pNode[1]->mNext = pNode[2];
2858 pNode[2]->mNext = mQuestionList;
2859 mQuestionList = pNode[0];
2860
2861 for (Index = 0; Index < 3; Index++) {
2862 if (VarIdStr[Index] != NULL) {
2863 delete VarIdStr[Index];
2864 }
2865 }
2866
2867 gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2868 gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2869 gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2870
2871 return;
2872
2873 Err:
2874 for (Index = 0; Index < 3; Index++) {
2875 if (pNode[Index] != NULL) {
2876 delete pNode[Index];
2877 }
2878
2879 if (VarIdStr[Index] != NULL) {
2880 delete VarIdStr[Index];
2881 }
2882 }
2883 }
2884
2885 VOID
2886 CVfrQuestionDB::RegisterRefQuestion (
2887 IN CHAR8 *Name,
2888 IN CHAR8 *BaseVarId,
2889 IN OUT EFI_QUESTION_ID &QuestionId
2890 )
2891 {
2892 SVfrQuestionNode *pNode[4] = {NULL, };
2893 UINT32 Len;
2894 CHAR8 *VarIdStr[4] = {NULL, };
2895 CHAR8 Index;
2896
2897 if (BaseVarId == NULL && Name == NULL) {
2898 return;
2899 }
2900
2901 if (BaseVarId != NULL) {
2902 Len = strlen (BaseVarId);
2903
2904 VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
2905 if (VarIdStr[0] != NULL) {
2906 strcpy (VarIdStr[0], BaseVarId);
2907 strcat (VarIdStr[0], ".QuestionId");
2908 }
2909 VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
2910 if (VarIdStr[1] != NULL) {
2911 strcpy (VarIdStr[1], BaseVarId);
2912 strcat (VarIdStr[1], ".FormId");
2913 }
2914 VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
2915 if (VarIdStr[2] != NULL) {
2916 strcpy (VarIdStr[2], BaseVarId);
2917 strcat (VarIdStr[2], ".FormSetGuid");
2918 }
2919 VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
2920 if (VarIdStr[3] != NULL) {
2921 strcpy (VarIdStr[3], BaseVarId);
2922 strcat (VarIdStr[3], ".DevicePath");
2923 }
2924 } else {
2925 Len = strlen (Name);
2926
2927 VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
2928 if (VarIdStr[0] != NULL) {
2929 strcpy (VarIdStr[0], Name);
2930 strcat (VarIdStr[0], ".QuestionId");
2931 }
2932 VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
2933 if (VarIdStr[1] != NULL) {
2934 strcpy (VarIdStr[1], Name);
2935 strcat (VarIdStr[1], ".FormId");
2936 }
2937 VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
2938 if (VarIdStr[2] != NULL) {
2939 strcpy (VarIdStr[2], Name);
2940 strcat (VarIdStr[2], ".FormSetGuid");
2941 }
2942 VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
2943 if (VarIdStr[3] != NULL) {
2944 strcpy (VarIdStr[3], Name);
2945 strcat (VarIdStr[3], ".DevicePath");
2946 }
2947 }
2948
2949 if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0])) == NULL) {
2950 goto Err;
2951 }
2952 if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1])) == NULL) {
2953 goto Err;
2954 }
2955 if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2])) == NULL) {
2956 goto Err;
2957 }
2958 if ((pNode[3] = new SVfrQuestionNode (Name, VarIdStr[3])) == NULL) {
2959 goto Err;
2960 }
2961
2962 if (QuestionId == EFI_QUESTION_ID_INVALID) {
2963 QuestionId = GetFreeQuestionId ();
2964 } else {
2965 if (ChekQuestionIdFree (QuestionId) == FALSE) {
2966 goto Err;
2967 }
2968 MarkQuestionIdUsed (QuestionId);
2969 }
2970
2971 pNode[0]->mQuestionId = QuestionId;
2972 pNode[1]->mQuestionId = QuestionId;
2973 pNode[2]->mQuestionId = QuestionId;
2974 pNode[3]->mQuestionId = QuestionId;
2975 pNode[0]->mQtype = QUESTION_REF;
2976 pNode[1]->mQtype = QUESTION_REF;
2977 pNode[2]->mQtype = QUESTION_REF;
2978 pNode[3]->mQtype = QUESTION_REF;
2979 pNode[0]->mNext = pNode[1];
2980 pNode[1]->mNext = pNode[2];
2981 pNode[2]->mNext = pNode[3];
2982 pNode[3]->mNext = mQuestionList;
2983 mQuestionList = pNode[0];
2984
2985 gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2986 gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2987 gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2988 gCFormPkg.DoPendingAssign (VarIdStr[3], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2989
2990 return;
2991
2992 Err:
2993 for (Index = 0; Index < 4; Index++) {
2994 if (pNode[Index] != NULL) {
2995 delete pNode[Index];
2996 }
2997
2998 if (VarIdStr[Index] != NULL) {
2999 delete VarIdStr[Index];
3000 }
3001 }
3002 }
3003
3004 EFI_VFR_RETURN_CODE
3005 CVfrQuestionDB::UpdateQuestionId (
3006 IN EFI_QUESTION_ID QId,
3007 IN EFI_QUESTION_ID NewQId
3008 )
3009 {
3010 SVfrQuestionNode *pNode = NULL;
3011
3012 if (QId == NewQId) {
3013 // don't update
3014 return VFR_RETURN_SUCCESS;
3015 }
3016
3017 //
3018 // For Framework Vfr, don't check question ID conflict.
3019 //
3020 if (!VfrCompatibleMode && ChekQuestionIdFree (NewQId) == FALSE) {
3021 return VFR_RETURN_REDEFINED;
3022 }
3023
3024 for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3025 if (pNode->mQuestionId == QId) {
3026 break;
3027 }
3028 }
3029
3030 if (pNode == NULL) {
3031 return VFR_RETURN_UNDEFINED;
3032 }
3033
3034 MarkQuestionIdUnused (QId);
3035 pNode->mQuestionId = NewQId;
3036 MarkQuestionIdUsed (NewQId);
3037
3038 gCFormPkg.DoPendingAssign (pNode->mVarIdStr, (VOID *)&NewQId, sizeof(EFI_QUESTION_ID));
3039
3040 return VFR_RETURN_SUCCESS;
3041 }
3042
3043 VOID
3044 CVfrQuestionDB::GetQuestionId (
3045 IN CHAR8 *Name,
3046 IN CHAR8 *VarIdStr,
3047 OUT EFI_QUESTION_ID &QuestionId,
3048 OUT UINT32 &BitMask,
3049 OUT EFI_QUESION_TYPE *QType
3050 )
3051 {
3052 SVfrQuestionNode *pNode;
3053
3054 QuestionId = EFI_QUESTION_ID_INVALID;
3055 BitMask = 0x00000000;
3056 if (QType != NULL) {
3057 *QType = QUESTION_NORMAL;
3058 }
3059
3060 if ((Name == NULL) && (VarIdStr == NULL)) {
3061 return ;
3062 }
3063
3064 for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3065 if (Name != NULL) {
3066 if (strcmp (pNode->mName, Name) != 0) {
3067 continue;
3068 }
3069 }
3070
3071 if (VarIdStr != NULL) {
3072 if (strcmp (pNode->mVarIdStr, VarIdStr) != 0) {
3073 continue;
3074 }
3075 }
3076
3077 QuestionId = pNode->mQuestionId;
3078 BitMask = pNode->mBitMask;
3079 if (QType != NULL) {
3080 *QType = pNode->mQtype;
3081 }
3082 break;
3083 }
3084
3085 return ;
3086 }
3087
3088 EFI_VFR_RETURN_CODE
3089 CVfrQuestionDB::FindQuestion (
3090 IN EFI_QUESTION_ID QuestionId
3091 )
3092 {
3093 SVfrQuestionNode *pNode;
3094
3095 if (QuestionId == EFI_QUESTION_ID_INVALID) {
3096 return VFR_RETURN_INVALID_PARAMETER;
3097 }
3098
3099 for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3100 if (pNode->mQuestionId == QuestionId) {
3101 return VFR_RETURN_SUCCESS;
3102 }
3103 }
3104
3105 return VFR_RETURN_UNDEFINED;
3106 }
3107
3108 EFI_VFR_RETURN_CODE
3109 CVfrQuestionDB::FindQuestion (
3110 IN CHAR8 *Name
3111 )
3112 {
3113 SVfrQuestionNode *pNode;
3114
3115 if (Name == NULL) {
3116 return VFR_RETURN_FATAL_ERROR;
3117 }
3118
3119 for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3120 if (strcmp (pNode->mName, Name) == 0) {
3121 return VFR_RETURN_SUCCESS;
3122 }
3123 }
3124
3125 return VFR_RETURN_UNDEFINED;
3126 }
3127
3128 CVfrStringDB::CVfrStringDB ()
3129 {
3130 mStringFileName = NULL;
3131 }
3132
3133 CVfrStringDB::~CVfrStringDB ()
3134 {
3135 if (mStringFileName != NULL) {
3136 delete mStringFileName;
3137 }
3138 mStringFileName = NULL;
3139 }
3140
3141
3142 VOID
3143 CVfrStringDB::SetStringFileName(IN CHAR8 *StringFileName)
3144 {
3145 UINT32 FileLen = 0;
3146
3147 if (StringFileName == NULL) {
3148 return;
3149 }
3150
3151 FileLen = strlen (StringFileName) + 1;
3152 mStringFileName = new CHAR8[FileLen];
3153 if (mStringFileName == NULL) {
3154 return;
3155 }
3156
3157 strcpy (mStringFileName, StringFileName);
3158 mStringFileName[FileLen - 1] = '\0';
3159 }
3160
3161
3162 /**
3163 Returns TRUE or FALSE whether SupportedLanguages contains the best matching language
3164 from a set of supported languages.
3165
3166 @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that
3167 contains a set of language codes.
3168 @param[in] Language A variable that contains pointers to Null-terminated
3169 ASCII strings that contain one language codes.
3170
3171 @retval FALSE The best matching language could not be found in SupportedLanguages.
3172 @retval TRUE The best matching language could be found in SupportedLanguages.
3173
3174 **/
3175 BOOLEAN
3176 CVfrStringDB::GetBestLanguage (
3177 IN CONST CHAR8 *SupportedLanguages,
3178 IN CHAR8 *Language
3179 )
3180 {
3181 UINTN CompareLength;
3182 UINTN LanguageLength;
3183 CONST CHAR8 *Supported;
3184
3185 if (SupportedLanguages == NULL || Language == NULL){
3186 return FALSE;
3187 }
3188
3189 //
3190 // Determine the length of the first RFC 4646 language code in Language
3191 //
3192 for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
3193
3194 //
3195 // Trim back the length of Language used until it is empty
3196 //
3197 while (LanguageLength > 0) {
3198 //
3199 // Loop through all language codes in SupportedLanguages
3200 //
3201 for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
3202 //
3203 // Skip ';' characters in Supported
3204 //
3205 for (; *Supported != '\0' && *Supported == ';'; Supported++);
3206 //
3207 // Determine the length of the next language code in Supported
3208 //
3209 for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
3210 //
3211 // If Language is longer than the Supported, then skip to the next language
3212 //
3213 if (LanguageLength > CompareLength) {
3214 continue;
3215 }
3216
3217 //
3218 // See if the first LanguageLength characters in Supported match Language
3219 //
3220 if (strncmp (Supported, Language, LanguageLength) == 0) {
3221 return TRUE;
3222 }
3223 }
3224
3225 //
3226 // Trim Language from the right to the next '-' character
3227 //
3228 for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
3229 }
3230
3231 //
3232 // No matches were found
3233 //
3234 return FALSE;
3235 }
3236
3237
3238 CHAR8 *
3239 CVfrStringDB::GetVarStoreNameFormStringId (
3240 IN EFI_STRING_ID StringId
3241 )
3242 {
3243 FILE *pInFile = NULL;
3244 UINT32 NameOffset;
3245 UINT32 Length;
3246 UINT8 *StringPtr;
3247 CHAR8 *StringName;
3248 CHAR16 *UnicodeString;
3249 CHAR8 *VarStoreName = NULL;
3250 CHAR8 *DestTmp;
3251 UINT8 *Current;
3252 EFI_STATUS Status;
3253 CHAR8 LineBuf[EFI_IFR_MAX_LENGTH];
3254 UINT8 BlockType;
3255 EFI_HII_STRING_PACKAGE_HDR *PkgHeader;
3256
3257 if (mStringFileName == '\0' ) {
3258 return NULL;
3259 }
3260
3261 if ((pInFile = fopen (mStringFileName, "rb")) == NULL) {
3262 return NULL;
3263 }
3264
3265 //
3266 // Get file length.
3267 //
3268 fseek (pInFile, 0, SEEK_END);
3269 Length = ftell (pInFile);
3270 fseek (pInFile, 0, SEEK_SET);
3271
3272 //
3273 // Get file data.
3274 //
3275 StringPtr = new UINT8[Length];
3276 if (StringPtr == NULL) {
3277 fclose (pInFile);
3278 return NULL;
3279 }
3280 fread ((char *)StringPtr, sizeof (UINT8), Length, pInFile);
3281 fclose (pInFile);
3282
3283 PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
3284 //
3285 // Check the String package.
3286 //
3287 if (PkgHeader->Header.Type != EFI_HII_PACKAGE_STRINGS) {
3288 delete StringPtr;
3289 return NULL;
3290 }
3291
3292 //
3293 // Search the language, get best language base on RFC 4647 matching algorithm.
3294 //
3295 Current = StringPtr;
3296 while (!GetBestLanguage ("en", PkgHeader->Language)) {
3297 Current += PkgHeader->Header.Length;
3298 PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current;
3299 //
3300 // If can't find string package base on language, just return the first string package.
3301 //
3302 if (Current - StringPtr >= Length) {
3303 Current = StringPtr;
3304 PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
3305 break;
3306 }
3307 }
3308
3309 Current += PkgHeader->HdrSize;
3310 //
3311 // Find the string block according the stringId.
3312 //
3313 Status = FindStringBlock(Current, StringId, &NameOffset, &BlockType);
3314 if (Status != EFI_SUCCESS) {
3315 delete StringPtr;
3316 return NULL;
3317 }
3318
3319 //
3320 // Get varstore name according the string type.
3321 //
3322 switch (BlockType) {
3323 case EFI_HII_SIBT_STRING_SCSU:
3324 case EFI_HII_SIBT_STRING_SCSU_FONT:
3325 case EFI_HII_SIBT_STRINGS_SCSU:
3326 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
3327 StringName = (CHAR8*)(Current + NameOffset);
3328 VarStoreName = new CHAR8[strlen(StringName) + 1];
3329 strcpy (VarStoreName, StringName);
3330 break;
3331 case EFI_HII_SIBT_STRING_UCS2:
3332 case EFI_HII_SIBT_STRING_UCS2_FONT:
3333 case EFI_HII_SIBT_STRINGS_UCS2:
3334 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
3335 UnicodeString = (CHAR16*)(Current + NameOffset);
3336 Length = GetUnicodeStringTextSize ((UINT8*)UnicodeString) ;
3337 DestTmp = new CHAR8[Length / 2 + 1];
3338 VarStoreName = DestTmp;
3339 while (*UnicodeString != '\0') {
3340 *(DestTmp++) = (CHAR8) *(UnicodeString++);
3341 }
3342 *DestTmp = '\0';
3343 break;
3344 default:
3345 break;
3346 }
3347
3348 delete StringPtr;
3349
3350 return VarStoreName;
3351 }
3352
3353 EFI_STATUS
3354 CVfrStringDB::FindStringBlock (
3355 IN UINT8 *StringData,
3356 IN EFI_STRING_ID StringId,
3357 OUT UINT32 *StringTextOffset,
3358 OUT UINT8 *BlockType
3359 )
3360 {
3361 UINT8 *BlockHdr;
3362 EFI_STRING_ID CurrentStringId;
3363 UINT32 BlockSize;
3364 UINT32 Index;
3365 UINT8 *StringTextPtr;
3366 UINT32 Offset;
3367 UINT16 StringCount;
3368 UINT16 SkipCount;
3369 UINT8 Length8;
3370 EFI_HII_SIBT_EXT2_BLOCK Ext2;
3371 UINT32 Length32;
3372 UINT32 StringSize;
3373
3374 CurrentStringId = 1;
3375
3376 //
3377 // Parse the string blocks to get the string text and font.
3378 //
3379 BlockHdr = StringData;
3380 BlockSize = 0;
3381 Offset = 0;
3382 while (*BlockHdr != EFI_HII_SIBT_END) {
3383 switch (*BlockHdr) {
3384 case EFI_HII_SIBT_STRING_SCSU:
3385 Offset = sizeof (EFI_HII_STRING_BLOCK);
3386 StringTextPtr = BlockHdr + Offset;
3387 BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
3388 CurrentStringId++;
3389 break;
3390
3391 case EFI_HII_SIBT_STRING_SCSU_FONT:
3392 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
3393 StringTextPtr = BlockHdr + Offset;
3394 BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
3395 CurrentStringId++;
3396 break;
3397
3398 case EFI_HII_SIBT_STRINGS_SCSU:
3399 memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
3400 StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);
3401 BlockSize += StringTextPtr - BlockHdr;
3402
3403 for (Index = 0; Index < StringCount; Index++) {
3404 BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
3405 if (CurrentStringId == StringId) {
3406 *BlockType = *BlockHdr;
3407 *StringTextOffset = StringTextPtr - StringData;
3408 return EFI_SUCCESS;
3409 }
3410 StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
3411 CurrentStringId++;
3412 }
3413 break;
3414
3415 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
3416 memcpy (
3417 &StringCount,
3418 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3419 sizeof (UINT16)
3420 );
3421 StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);
3422 BlockSize += StringTextPtr - BlockHdr;
3423
3424 for (Index = 0; Index < StringCount; Index++) {
3425 BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
3426 if (CurrentStringId == StringId) {
3427 *BlockType = *BlockHdr;
3428 *StringTextOffset = StringTextPtr - StringData;
3429 return EFI_SUCCESS;
3430 }
3431 StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
3432 CurrentStringId++;
3433 }
3434 break;
3435
3436 case EFI_HII_SIBT_STRING_UCS2:
3437 Offset = sizeof (EFI_HII_STRING_BLOCK);
3438 StringTextPtr = BlockHdr + Offset;
3439 //
3440 // Use StringSize to store the size of the specified string, including the NULL
3441 // terminator.
3442 //
3443 StringSize = GetUnicodeStringTextSize (StringTextPtr);
3444 BlockSize += Offset + StringSize;
3445 CurrentStringId++;
3446 break;
3447
3448 case EFI_HII_SIBT_STRING_UCS2_FONT:
3449 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
3450 StringTextPtr = BlockHdr + Offset;
3451 //
3452 // Use StrSize to store the size of the specified string, including the NULL
3453 // terminator.
3454 //
3455 StringSize = GetUnicodeStringTextSize (StringTextPtr);
3456 BlockSize += Offset + StringSize;
3457 CurrentStringId++;
3458 break;
3459
3460 case EFI_HII_SIBT_STRINGS_UCS2:
3461 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
3462 StringTextPtr = BlockHdr + Offset;
3463 BlockSize += Offset;
3464 memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
3465 for (Index = 0; Index < StringCount; Index++) {
3466 StringSize = GetUnicodeStringTextSize (StringTextPtr);
3467 BlockSize += StringSize;
3468 if (CurrentStringId == StringId) {
3469 *BlockType = *BlockHdr;
3470 *StringTextOffset = StringTextPtr - StringData;
3471 return EFI_SUCCESS;
3472 }
3473 StringTextPtr = StringTextPtr + StringSize;
3474 CurrentStringId++;
3475 }
3476 break;
3477
3478 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
3479 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
3480 StringTextPtr = BlockHdr + Offset;
3481 BlockSize += Offset;
3482 memcpy (
3483 &StringCount,
3484 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3485 sizeof (UINT16)
3486 );
3487 for (Index = 0; Index < StringCount; Index++) {
3488 StringSize = GetUnicodeStringTextSize (StringTextPtr);
3489 BlockSize += StringSize;
3490 if (CurrentStringId == StringId) {
3491 *BlockType = *BlockHdr;
3492 *StringTextOffset = StringTextPtr - StringData;
3493 return EFI_SUCCESS;
3494 }
3495 StringTextPtr = StringTextPtr + StringSize;
3496 CurrentStringId++;
3497 }
3498 break;
3499
3500 case EFI_HII_SIBT_DUPLICATE:
3501 if (CurrentStringId == StringId) {
3502 //
3503 // Incoming StringId is an id of a duplicate string block.
3504 // Update the StringId to be the previous string block.
3505 // Go back to the header of string block to search.
3506 //
3507 memcpy (
3508 &StringId,
3509 BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
3510 sizeof (EFI_STRING_ID)
3511 );
3512 CurrentStringId = 1;
3513 BlockSize = 0;
3514 } else {
3515 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
3516 CurrentStringId++;
3517 }
3518 break;
3519
3520 case EFI_HII_SIBT_SKIP1:
3521 SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
3522 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
3523 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
3524 break;
3525
3526 case EFI_HII_SIBT_SKIP2:
3527 memcpy (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
3528 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
3529 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
3530 break;
3531
3532 case EFI_HII_SIBT_EXT1:
3533 memcpy (
3534 &Length8,
3535 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3536 sizeof (UINT8)
3537 );
3538 BlockSize += Length8;
3539 break;
3540
3541 case EFI_HII_SIBT_EXT2:
3542 memcpy (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
3543 BlockSize += Ext2.Length;
3544 break;
3545
3546 case EFI_HII_SIBT_EXT4:
3547 memcpy (
3548 &Length32,
3549 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3550 sizeof (UINT32)
3551 );
3552
3553 BlockSize += Length32;
3554 break;
3555
3556 default:
3557 break;
3558 }
3559
3560 if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) {
3561 *StringTextOffset = BlockHdr - StringData + Offset;
3562 *BlockType = *BlockHdr;
3563
3564 if (StringId == CurrentStringId - 1) {
3565 //
3566 // if only one skip item, return EFI_NOT_FOUND.
3567 //
3568 if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) {
3569 return EFI_NOT_FOUND;
3570 } else {
3571 return EFI_SUCCESS;
3572 }
3573 }
3574
3575 if (StringId < CurrentStringId - 1) {
3576 return EFI_NOT_FOUND;
3577 }
3578 }
3579 BlockHdr = StringData + BlockSize;
3580 }
3581
3582 return EFI_NOT_FOUND;
3583 }
3584
3585 UINT32
3586 CVfrStringDB::GetUnicodeStringTextSize (
3587 IN UINT8 *StringSrc
3588 )
3589 {
3590 UINT32 StringSize;
3591 CHAR16 *StringPtr;
3592
3593 StringSize = sizeof (CHAR16);
3594 StringPtr = (UINT16*)StringSrc;
3595 while (*StringPtr++ != L'\0') {
3596 StringSize += sizeof (CHAR16);
3597 }
3598
3599 return StringSize;
3600 }
3601
3602 BOOLEAN VfrCompatibleMode = FALSE;
3603
3604 CVfrVarDataTypeDB gCVfrVarDataTypeDB;
3605
3606