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