1 /** @file
2 
3   Vfr common library functions.
4 
5 Copyright (c) 2004 - 2016, 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   ARRAY_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   ARRAY_SAFE_FREE (mName);
204   ARRAY_SAFE_FREE (mGuid);
205   ARRAY_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 (&mGuid, 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 (&mGuid, 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   mBufferFieldInfoListHead = NULL;
1423   mBufferFieldInfoListTail = NULL;
1424 }
1425 
~CVfrDataStorage(VOID)1426 CVfrDataStorage::~CVfrDataStorage (
1427   VOID
1428   )
1429 {
1430   SVfrVarStorageNode *pNode;
1431 
1432   while (mBufferVarStoreList != NULL) {
1433     pNode = mBufferVarStoreList;
1434     mBufferVarStoreList = mBufferVarStoreList->mNext;
1435     delete pNode;
1436   }
1437   while (mEfiVarStoreList != NULL) {
1438     pNode = mEfiVarStoreList;
1439     mEfiVarStoreList = mEfiVarStoreList->mNext;
1440     delete pNode;
1441   }
1442   while (mNameVarStoreList != NULL) {
1443     pNode = mNameVarStoreList;
1444     mNameVarStoreList = mNameVarStoreList->mNext;
1445     delete pNode;
1446   }
1447   if (mNewVarStorageNode != NULL) {
1448     delete mNewVarStorageNode;
1449   }
1450 }
1451 
1452 EFI_VARSTORE_ID
GetFreeVarStoreId(EFI_VFR_VARSTORE_TYPE VarType)1453 CVfrDataStorage::GetFreeVarStoreId (
1454   EFI_VFR_VARSTORE_TYPE VarType
1455   )
1456 {
1457   UINT32  Index, Mask, Offset;
1458 
1459   //
1460   // Assign the different ID range for the different type VarStore to support Framework Vfr
1461   //
1462   Index = 0;
1463   if ((!VfrCompatibleMode) || (VarType == EFI_VFR_VARSTORE_BUFFER)) {
1464     Index = 0;
1465   } else if (VarType == EFI_VFR_VARSTORE_EFI) {
1466     Index = 1;
1467   } else if (VarType == EFI_VFR_VARSTORE_NAME) {
1468     Index = 2;
1469   }
1470 
1471   for (; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) {
1472     if (mFreeVarStoreIdBitMap[Index] != 0xFFFFFFFF) {
1473       break;
1474     }
1475   }
1476 
1477   if (Index == EFI_FREE_VARSTORE_ID_BITMAP_SIZE) {
1478     return EFI_VARSTORE_ID_INVALID;
1479   }
1480 
1481   for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
1482     if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) {
1483       mFreeVarStoreIdBitMap[Index] |= Mask;
1484       return (EFI_VARSTORE_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset);
1485     }
1486   }
1487 
1488   return EFI_VARSTORE_ID_INVALID;
1489 }
1490 
1491 BOOLEAN
ChekVarStoreIdFree(IN EFI_VARSTORE_ID VarStoreId)1492 CVfrDataStorage::ChekVarStoreIdFree (
1493   IN EFI_VARSTORE_ID VarStoreId
1494   )
1495 {
1496   UINT32 Index  = (VarStoreId / EFI_BITS_PER_UINT32);
1497   UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
1498 
1499   return (mFreeVarStoreIdBitMap[Index] & (0x80000000 >> Offset)) == 0;
1500 }
1501 
1502 VOID
MarkVarStoreIdUsed(IN EFI_VARSTORE_ID VarStoreId)1503 CVfrDataStorage::MarkVarStoreIdUsed (
1504   IN EFI_VARSTORE_ID VarStoreId
1505   )
1506 {
1507   UINT32 Index  = (VarStoreId / EFI_BITS_PER_UINT32);
1508   UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
1509 
1510   mFreeVarStoreIdBitMap[Index] |= (0x80000000 >> Offset);
1511 }
1512 
1513 VOID
MarkVarStoreIdUnused(IN EFI_VARSTORE_ID VarStoreId)1514 CVfrDataStorage::MarkVarStoreIdUnused (
1515   IN EFI_VARSTORE_ID VarStoreId
1516   )
1517 {
1518   UINT32 Index  = (VarStoreId / EFI_BITS_PER_UINT32);
1519   UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32);
1520 
1521   mFreeVarStoreIdBitMap[Index] &= ~(0x80000000 >> Offset);
1522 }
1523 
1524 EFI_VFR_RETURN_CODE
DeclareNameVarStoreBegin(IN CHAR8 * StoreName,IN EFI_VARSTORE_ID VarStoreId)1525 CVfrDataStorage::DeclareNameVarStoreBegin (
1526   IN CHAR8           *StoreName,
1527   IN EFI_VARSTORE_ID VarStoreId
1528   )
1529 {
1530   SVfrVarStorageNode *pNode = NULL;
1531   EFI_VARSTORE_ID    TmpVarStoreId;
1532 
1533   if (StoreName == NULL) {
1534     return VFR_RETURN_FATAL_ERROR;
1535   }
1536 
1537   if (GetVarStoreId (StoreName, &TmpVarStoreId) == VFR_RETURN_SUCCESS) {
1538     return VFR_RETURN_REDEFINED;
1539   }
1540 
1541   if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1542     VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME);
1543   } else {
1544     if (ChekVarStoreIdFree (VarStoreId) == FALSE) {
1545       return VFR_RETURN_VARSTOREID_REDEFINED;
1546     }
1547     MarkVarStoreIdUsed (VarStoreId);
1548   }
1549 
1550   if ((pNode = new SVfrVarStorageNode (StoreName, VarStoreId)) == NULL) {
1551     return VFR_RETURN_UNDEFINED;
1552   }
1553 
1554   mNewVarStorageNode = pNode;
1555 
1556   return VFR_RETURN_SUCCESS;
1557 }
1558 
1559 EFI_VFR_RETURN_CODE
NameTableAddItem(IN EFI_STRING_ID Item)1560 CVfrDataStorage::NameTableAddItem (
1561   IN EFI_STRING_ID  Item
1562   )
1563 {
1564   EFI_VARSTORE_ID *NewTable, *OldTable;
1565   UINT32          TableSize;
1566 
1567   OldTable  = mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable;
1568   TableSize = mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize;
1569 
1570   if ((TableSize != 0) && ((TableSize % DEFAULT_NAME_TABLE_ITEMS) == 0)) {
1571     if ((NewTable = new EFI_VARSTORE_ID[TableSize + DEFAULT_NAME_TABLE_ITEMS]) == NULL) {
1572       return VFR_RETURN_OUT_FOR_RESOURCES;
1573     }
1574     memcpy (NewTable, OldTable, TableSize);
1575     mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable = NewTable;
1576   }
1577 
1578   mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable[TableSize++] = Item;
1579   mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize = TableSize;
1580 
1581   return VFR_RETURN_SUCCESS;
1582 }
1583 
1584 EFI_VFR_RETURN_CODE
DeclareNameVarStoreEnd(IN EFI_GUID * Guid)1585 CVfrDataStorage::DeclareNameVarStoreEnd (
1586   IN EFI_GUID *Guid
1587   )
1588 {
1589   mNewVarStorageNode->mGuid = *Guid;
1590   mNewVarStorageNode->mNext = mNameVarStoreList;
1591   mNameVarStoreList         = mNewVarStorageNode;
1592 
1593   mNewVarStorageNode        = NULL;
1594 
1595   return VFR_RETURN_SUCCESS;
1596 }
1597 
1598 EFI_VFR_RETURN_CODE
DeclareEfiVarStore(IN CHAR8 * StoreName,IN EFI_GUID * Guid,IN EFI_STRING_ID NameStrId,IN UINT32 VarSize,IN BOOLEAN Flag)1599 CVfrDataStorage::DeclareEfiVarStore (
1600   IN CHAR8          *StoreName,
1601   IN EFI_GUID       *Guid,
1602   IN EFI_STRING_ID  NameStrId,
1603   IN UINT32         VarSize,
1604   IN BOOLEAN        Flag
1605   )
1606 {
1607   SVfrVarStorageNode *pNode;
1608   EFI_VARSTORE_ID    VarStoreId;
1609 
1610   if ((StoreName == NULL) || (Guid == NULL)) {
1611     return VFR_RETURN_FATAL_ERROR;
1612   }
1613 
1614   if (VarSize > sizeof (UINT64)) {
1615     return VFR_RETURN_EFIVARSTORE_SIZE_ERROR;
1616   }
1617 
1618   if (GetVarStoreId (StoreName, &VarStoreId, Guid) == VFR_RETURN_SUCCESS) {
1619     return VFR_RETURN_REDEFINED;
1620   }
1621 
1622   VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI);
1623   if ((pNode = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, NameStrId, VarSize, Flag)) == NULL) {
1624     return VFR_RETURN_OUT_FOR_RESOURCES;
1625   }
1626 
1627   pNode->mNext       = mEfiVarStoreList;
1628   mEfiVarStoreList   = pNode;
1629 
1630   return VFR_RETURN_SUCCESS;
1631 }
1632 
1633 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)1634 CVfrDataStorage::DeclareBufferVarStore (
1635   IN CHAR8             *StoreName,
1636   IN EFI_GUID          *Guid,
1637   IN CVfrVarDataTypeDB *DataTypeDB,
1638   IN CHAR8             *TypeName,
1639   IN EFI_VARSTORE_ID   VarStoreId,
1640   IN BOOLEAN           Flag
1641   )
1642 {
1643   SVfrVarStorageNode   *pNew = NULL;
1644   SVfrDataType         *pDataType = NULL;
1645   EFI_VARSTORE_ID      TempVarStoreId;
1646 
1647   if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) {
1648     return VFR_RETURN_FATAL_ERROR;
1649   }
1650 
1651   if (GetVarStoreId (StoreName, &TempVarStoreId, Guid) == VFR_RETURN_SUCCESS) {
1652     return VFR_RETURN_REDEFINED;
1653   }
1654 
1655   CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS);
1656 
1657   if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1658     VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_BUFFER);
1659   } else {
1660     if (ChekVarStoreIdFree (VarStoreId) == FALSE) {
1661       return VFR_RETURN_VARSTOREID_REDEFINED;
1662     }
1663     MarkVarStoreIdUsed (VarStoreId);
1664   }
1665 
1666   if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, Flag)) == NULL) {
1667     return VFR_RETURN_OUT_FOR_RESOURCES;
1668   }
1669 
1670   pNew->mNext         = mBufferVarStoreList;
1671   mBufferVarStoreList = pNew;
1672 
1673   if (gCVfrBufferConfig.Register(StoreName, Guid) != 0) {
1674     return VFR_RETURN_FATAL_ERROR;
1675   }
1676 
1677   return VFR_RETURN_SUCCESS;
1678 }
1679 
1680 EFI_VFR_RETURN_CODE
GetVarStoreByDataType(IN CHAR8 * DataTypeName,OUT SVfrVarStorageNode ** VarNode,IN EFI_GUID * VarGuid)1681 CVfrDataStorage::GetVarStoreByDataType (
1682   IN  CHAR8              *DataTypeName,
1683   OUT SVfrVarStorageNode **VarNode,
1684   IN  EFI_GUID           *VarGuid
1685   )
1686 {
1687   SVfrVarStorageNode    *pNode;
1688   SVfrVarStorageNode    *MatchNode;
1689 
1690   //
1691   // Framework VFR uses Data type name as varstore name, so don't need check again.
1692   //
1693   if (VfrCompatibleMode) {
1694     return VFR_RETURN_UNDEFINED;
1695   }
1696 
1697   MatchNode = NULL;
1698   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1699     if (strcmp (pNode->mStorageInfo.mDataType->mTypeName, DataTypeName) != 0) {
1700       continue;
1701     }
1702 
1703     if ((VarGuid != NULL)) {
1704       if (memcmp (VarGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) {
1705         *VarNode = pNode;
1706         return VFR_RETURN_SUCCESS;
1707       }
1708     } else {
1709       if (MatchNode == NULL) {
1710         MatchNode = pNode;
1711       } else {
1712         //
1713         // More than one varstores referred the same data structures.
1714         //
1715         return VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR;
1716       }
1717     }
1718   }
1719 
1720   if (MatchNode == NULL) {
1721     return VFR_RETURN_UNDEFINED;
1722   }
1723 
1724   *VarNode = MatchNode;
1725   return VFR_RETURN_SUCCESS;
1726 }
1727 
1728 EFI_VARSTORE_ID
CheckGuidField(IN SVfrVarStorageNode * pNode,IN EFI_GUID * StoreGuid,IN BOOLEAN * HasFoundOne,OUT EFI_VFR_RETURN_CODE * ReturnCode)1729 CVfrDataStorage::CheckGuidField (
1730   IN  SVfrVarStorageNode   *pNode,
1731   IN  EFI_GUID             *StoreGuid,
1732   IN  BOOLEAN              *HasFoundOne,
1733   OUT EFI_VFR_RETURN_CODE  *ReturnCode
1734   )
1735 {
1736   if (StoreGuid != NULL) {
1737     //
1738     // If has guid info, compare the guid filed.
1739     //
1740     if (memcmp (StoreGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) {
1741       //
1742       // Both name and guid are same, this this varstore.
1743       //
1744       mCurrVarStorageNode = pNode;
1745       *ReturnCode = VFR_RETURN_SUCCESS;
1746       return TRUE;
1747     }
1748   } else {
1749     //
1750     // Not has Guid field, check whether this name is the only one.
1751     //
1752     if (*HasFoundOne) {
1753       //
1754       // The name has conflict, return name redefined.
1755       //
1756       *ReturnCode = VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR;
1757       return TRUE;
1758     }
1759 
1760     *HasFoundOne = TRUE;
1761     mCurrVarStorageNode = pNode;
1762   }
1763 
1764   return FALSE;
1765 }
1766 
1767 /**
1768   Base on the input store name and guid to find the varstore id.
1769 
1770   If both name and guid are inputed, base on the name and guid to
1771   found the varstore. If only name inputed, base on the name to
1772   found the varstore and go on to check whether more than one varstore
1773   has the same name. If only has found one varstore, return this
1774   varstore; if more than one varstore has same name, return varstore
1775   name redefined error. If no varstore found by varstore name, call
1776   function GetVarStoreByDataType and use inputed varstore name as
1777   data type name to search.
1778 **/
1779 EFI_VFR_RETURN_CODE
GetVarStoreId(IN CHAR8 * StoreName,OUT EFI_VARSTORE_ID * VarStoreId,IN EFI_GUID * StoreGuid)1780 CVfrDataStorage::GetVarStoreId (
1781   IN  CHAR8           *StoreName,
1782   OUT EFI_VARSTORE_ID *VarStoreId,
1783   IN  EFI_GUID        *StoreGuid
1784   )
1785 {
1786   EFI_VFR_RETURN_CODE   ReturnCode;
1787   SVfrVarStorageNode    *pNode;
1788   BOOLEAN               HasFoundOne = FALSE;
1789 
1790   mCurrVarStorageNode = NULL;
1791 
1792   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1793     if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
1794       if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
1795         *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1796         return ReturnCode;
1797       }
1798     }
1799   }
1800 
1801   for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1802     if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
1803       if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
1804         *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1805         return ReturnCode;
1806       }
1807     }
1808   }
1809 
1810   for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1811     if (strcmp (pNode->mVarStoreName, StoreName) == 0) {
1812       if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) {
1813         *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1814         return ReturnCode;
1815       }
1816     }
1817   }
1818 
1819   if (HasFoundOne) {
1820     *VarStoreId = mCurrVarStorageNode->mVarStoreId;
1821     return VFR_RETURN_SUCCESS;
1822   }
1823 
1824   *VarStoreId         = EFI_VARSTORE_ID_INVALID;
1825 
1826   //
1827   // Assume that Data strucutre name is used as StoreName, and check again.
1828   //
1829   ReturnCode = GetVarStoreByDataType (StoreName, &pNode, StoreGuid);
1830   if (pNode != NULL) {
1831     mCurrVarStorageNode = pNode;
1832     *VarStoreId = pNode->mVarStoreId;
1833   }
1834 
1835   return ReturnCode;
1836 }
1837 
1838 EFI_VFR_RETURN_CODE
GetBufferVarStoreDataTypeName(IN EFI_VARSTORE_ID VarStoreId,OUT CHAR8 ** DataTypeName)1839 CVfrDataStorage::GetBufferVarStoreDataTypeName (
1840   IN  EFI_VARSTORE_ID        VarStoreId,
1841   OUT CHAR8                  **DataTypeName
1842   )
1843 {
1844   SVfrVarStorageNode    *pNode;
1845 
1846   if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1847     return VFR_RETURN_FATAL_ERROR;
1848   }
1849 
1850   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1851     if (pNode->mVarStoreId == VarStoreId) {
1852       *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName;
1853       return VFR_RETURN_SUCCESS;
1854     }
1855   }
1856 
1857   return VFR_RETURN_UNDEFINED;
1858 }
1859 
1860 EFI_VFR_VARSTORE_TYPE
GetVarStoreType(IN EFI_VARSTORE_ID VarStoreId)1861 CVfrDataStorage::GetVarStoreType (
1862   IN  EFI_VARSTORE_ID        VarStoreId
1863   )
1864 {
1865   SVfrVarStorageNode    *pNode;
1866   EFI_VFR_VARSTORE_TYPE VarStoreType;
1867 
1868   VarStoreType = EFI_VFR_VARSTORE_INVALID;
1869 
1870   if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1871     return VarStoreType;
1872   }
1873 
1874   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1875     if (pNode->mVarStoreId == VarStoreId) {
1876       VarStoreType = pNode->mVarStoreType;
1877       return VarStoreType;
1878     }
1879   }
1880 
1881   for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1882     if (pNode->mVarStoreId == VarStoreId) {
1883       VarStoreType = pNode->mVarStoreType;
1884       return VarStoreType;
1885     }
1886   }
1887 
1888   for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1889     if (pNode->mVarStoreId == VarStoreId) {
1890       VarStoreType = pNode->mVarStoreType;
1891       return VarStoreType;
1892     }
1893   }
1894 
1895   return VarStoreType;
1896 }
1897 
1898 EFI_GUID *
GetVarStoreGuid(IN EFI_VARSTORE_ID VarStoreId)1899 CVfrDataStorage::GetVarStoreGuid (
1900   IN  EFI_VARSTORE_ID        VarStoreId
1901   )
1902 {
1903   SVfrVarStorageNode    *pNode;
1904   EFI_GUID              *VarGuid;
1905 
1906   VarGuid = NULL;
1907 
1908   if (VarStoreId == EFI_VARSTORE_ID_INVALID) {
1909     return VarGuid;
1910   }
1911 
1912   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1913     if (pNode->mVarStoreId == VarStoreId) {
1914       VarGuid = &pNode->mGuid;
1915       return VarGuid;
1916     }
1917   }
1918 
1919   for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1920     if (pNode->mVarStoreId == VarStoreId) {
1921       VarGuid = &pNode->mGuid;
1922       return VarGuid;
1923     }
1924   }
1925 
1926   for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1927     if (pNode->mVarStoreId == VarStoreId) {
1928       VarGuid = &pNode->mGuid;
1929       return VarGuid;
1930     }
1931   }
1932 
1933   return VarGuid;
1934 }
1935 
1936 EFI_VFR_RETURN_CODE
GetVarStoreName(IN EFI_VARSTORE_ID VarStoreId,OUT CHAR8 ** VarStoreName)1937 CVfrDataStorage::GetVarStoreName (
1938   IN  EFI_VARSTORE_ID VarStoreId,
1939   OUT CHAR8           **VarStoreName
1940   )
1941 {
1942   SVfrVarStorageNode    *pNode;
1943 
1944   if (VarStoreName == NULL) {
1945     return VFR_RETURN_FATAL_ERROR;
1946   }
1947 
1948   for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1949     if (pNode->mVarStoreId == VarStoreId) {
1950       *VarStoreName = pNode->mVarStoreName;
1951       return VFR_RETURN_SUCCESS;
1952     }
1953   }
1954 
1955   for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1956     if (pNode->mVarStoreId == VarStoreId) {
1957       *VarStoreName = pNode->mVarStoreName;
1958       return VFR_RETURN_SUCCESS;
1959     }
1960   }
1961 
1962   for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) {
1963     if (pNode->mVarStoreId == VarStoreId) {
1964       *VarStoreName = pNode->mVarStoreName;
1965       return VFR_RETURN_SUCCESS;
1966     }
1967   }
1968 
1969   *VarStoreName = NULL;
1970   return VFR_RETURN_UNDEFINED;
1971 }
1972 
1973 EFI_VFR_RETURN_CODE
GetEfiVarStoreInfo(IN OUT EFI_VARSTORE_INFO * Info)1974 CVfrDataStorage::GetEfiVarStoreInfo (
1975   IN OUT EFI_VARSTORE_INFO  *Info
1976   )
1977 {
1978   if (Info == NULL) {
1979     return VFR_RETURN_FATAL_ERROR;
1980   }
1981 
1982   if (mCurrVarStorageNode == NULL) {
1983     return VFR_RETURN_GET_EFIVARSTORE_ERROR;
1984   }
1985 
1986   Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarName;
1987   Info->mVarTotalSize  = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarSize;
1988   switch (Info->mVarTotalSize) {
1989   case 1:
1990     Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
1991     break;
1992   case 2:
1993     Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_16;
1994     break;
1995   case 4:
1996     Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_32;
1997     break;
1998   case 8:
1999     Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_64;
2000     break;
2001   default :
2002     return VFR_RETURN_FATAL_ERROR;
2003   }
2004 
2005   return VFR_RETURN_SUCCESS;
2006 }
2007 
2008 EFI_VFR_RETURN_CODE
AddBufferVarStoreFieldInfo(IN EFI_VARSTORE_INFO * Info)2009 CVfrDataStorage::AddBufferVarStoreFieldInfo (
2010   IN EFI_VARSTORE_INFO  *Info
2011   )
2012 {
2013   BufferVarStoreFieldInfoNode *pNew;
2014 
2015   if ((pNew = new BufferVarStoreFieldInfoNode(Info)) == NULL) {
2016     return VFR_RETURN_FATAL_ERROR;
2017   }
2018 
2019   if (mBufferFieldInfoListHead == NULL) {
2020     mBufferFieldInfoListHead = pNew;
2021     mBufferFieldInfoListTail= pNew;
2022   } else {
2023     mBufferFieldInfoListTail->mNext = pNew;
2024     mBufferFieldInfoListTail = pNew;
2025   }
2026 
2027   return VFR_RETURN_SUCCESS;
2028 }
2029 
2030 EFI_VFR_RETURN_CODE
GetBufferVarStoreFieldInfo(IN OUT EFI_VARSTORE_INFO * Info)2031 CVfrDataStorage::GetBufferVarStoreFieldInfo (
2032   IN OUT EFI_VARSTORE_INFO  *Info
2033   )
2034 {
2035   BufferVarStoreFieldInfoNode *pNode;
2036 
2037   pNode = mBufferFieldInfoListHead;
2038   while (pNode != NULL) {
2039     if (Info->mVarStoreId == pNode->mVarStoreInfo.mVarStoreId &&
2040       Info->mInfo.mVarOffset == pNode->mVarStoreInfo.mInfo.mVarOffset) {
2041       Info->mVarTotalSize = pNode->mVarStoreInfo.mVarTotalSize;
2042       Info->mVarType      = pNode->mVarStoreInfo.mVarType;
2043       return VFR_RETURN_SUCCESS;
2044     }
2045     pNode = pNode->mNext;
2046   }
2047   return VFR_RETURN_FATAL_ERROR;
2048 }
2049 
2050 EFI_VFR_RETURN_CODE
GetNameVarStoreInfo(OUT EFI_VARSTORE_INFO * Info,IN UINT32 Index)2051 CVfrDataStorage::GetNameVarStoreInfo (
2052   OUT EFI_VARSTORE_INFO  *Info,
2053   IN  UINT32             Index
2054   )
2055 {
2056   if (Info == NULL) {
2057     return VFR_RETURN_FATAL_ERROR;
2058   }
2059 
2060   if (mCurrVarStorageNode == NULL) {
2061     return VFR_RETURN_GET_NVVARSTORE_ERROR;
2062   }
2063 
2064   //
2065   // Framework Vfr file Index is from 1, but Uefi Vfr file Index is from 0.
2066   //
2067   if (VfrCompatibleMode) {
2068     if (Index == 0) {
2069       return VFR_RETURN_ERROR_ARRARY_NUM;
2070     }
2071     Index --;
2072   }
2073 
2074   Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mNameSpace.mNameTable[Index];
2075 
2076   return VFR_RETURN_SUCCESS;
2077 }
2078 
SVfrDefaultStoreNode(IN EFI_IFR_DEFAULTSTORE * ObjBinAddr,IN CHAR8 * RefName,IN EFI_STRING_ID DefaultStoreNameId,IN UINT16 DefaultId)2079 SVfrDefaultStoreNode::SVfrDefaultStoreNode (
2080   IN EFI_IFR_DEFAULTSTORE *ObjBinAddr,
2081   IN CHAR8                *RefName,
2082   IN EFI_STRING_ID        DefaultStoreNameId,
2083   IN UINT16               DefaultId
2084   )
2085 {
2086   mObjBinAddr = ObjBinAddr;
2087 
2088   if (RefName != NULL) {
2089     mRefName          = new CHAR8[strlen (RefName) + 1];
2090     strcpy (mRefName, RefName);
2091   } else {
2092     mRefName          = NULL;
2093   }
2094 
2095   mNext               = NULL;
2096   mDefaultId          = DefaultId;
2097   mDefaultStoreNameId = DefaultStoreNameId;
2098 }
2099 
~SVfrDefaultStoreNode(VOID)2100 SVfrDefaultStoreNode::~SVfrDefaultStoreNode (
2101   VOID
2102   )
2103 {
2104   if (mRefName != NULL) {
2105     delete[] mRefName;
2106   }
2107 }
2108 
CVfrDefaultStore(VOID)2109 CVfrDefaultStore::CVfrDefaultStore (
2110   VOID
2111   )
2112 {
2113   mDefaultStoreList = NULL;
2114 }
2115 
~CVfrDefaultStore(VOID)2116 CVfrDefaultStore::~CVfrDefaultStore (
2117   VOID
2118   )
2119 {
2120   SVfrDefaultStoreNode *pTmp = NULL;
2121 
2122   while (mDefaultStoreList != NULL) {
2123     pTmp = mDefaultStoreList;
2124     mDefaultStoreList = mDefaultStoreList->mNext;
2125     delete pTmp;
2126   }
2127 }
2128 
2129 EFI_VFR_RETURN_CODE
RegisterDefaultStore(IN CHAR8 * ObjBinAddr,IN CHAR8 * RefName,IN EFI_STRING_ID DefaultStoreNameId,IN UINT16 DefaultId)2130 CVfrDefaultStore::RegisterDefaultStore (
2131   IN CHAR8                *ObjBinAddr,
2132   IN CHAR8                *RefName,
2133   IN EFI_STRING_ID        DefaultStoreNameId,
2134   IN UINT16               DefaultId
2135   )
2136 {
2137   SVfrDefaultStoreNode *pNode = NULL;
2138 
2139   if (RefName == NULL) {
2140     return VFR_RETURN_FATAL_ERROR;
2141   }
2142 
2143   for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2144     if (strcmp (pNode->mRefName, RefName) == 0) {
2145       return VFR_RETURN_REDEFINED;
2146     }
2147   }
2148 
2149   if ((pNode = new SVfrDefaultStoreNode ((EFI_IFR_DEFAULTSTORE *)ObjBinAddr, RefName, DefaultStoreNameId, DefaultId)) == NULL) {
2150     return VFR_RETURN_OUT_FOR_RESOURCES;
2151   }
2152 
2153   pNode->mNext               = mDefaultStoreList;
2154   mDefaultStoreList          = pNode;
2155 
2156   return VFR_RETURN_SUCCESS;
2157 }
2158 
2159 /*
2160  * assign new reference name or new default store name id only if
2161  * the original is invalid
2162  */
2163 EFI_VFR_RETURN_CODE
ReRegisterDefaultStoreById(IN UINT16 DefaultId,IN CHAR8 * RefName,IN EFI_STRING_ID DefaultStoreNameId)2164 CVfrDefaultStore::ReRegisterDefaultStoreById (
2165   IN UINT16          DefaultId,
2166   IN CHAR8           *RefName,
2167   IN EFI_STRING_ID   DefaultStoreNameId
2168   )
2169 {
2170   SVfrDefaultStoreNode *pNode = NULL;
2171 
2172   for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2173     if (pNode->mDefaultId == DefaultId) {
2174       break;
2175     }
2176   }
2177 
2178   if (pNode == NULL) {
2179     return VFR_RETURN_UNDEFINED;
2180   } else {
2181     if (pNode->mDefaultStoreNameId == EFI_STRING_ID_INVALID) {
2182       pNode->mDefaultStoreNameId  = DefaultStoreNameId;
2183       if (pNode->mObjBinAddr != NULL) {
2184         pNode->mObjBinAddr->DefaultName = DefaultStoreNameId;
2185       }
2186     } else {
2187       return VFR_RETURN_REDEFINED;
2188     }
2189 
2190     if (RefName != NULL) {
2191       delete pNode->mRefName;
2192       pNode->mRefName = new CHAR8[strlen (RefName) + 1];
2193       if (pNode->mRefName != NULL) {
2194         strcpy (pNode->mRefName, RefName);
2195       }
2196     }
2197   }
2198 
2199   return VFR_RETURN_SUCCESS;
2200 }
2201 
2202 BOOLEAN
DefaultIdRegistered(IN UINT16 DefaultId)2203 CVfrDefaultStore::DefaultIdRegistered (
2204   IN UINT16          DefaultId
2205   )
2206 {
2207   SVfrDefaultStoreNode *pNode = NULL;
2208 
2209   for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2210     if (pNode->mDefaultId == DefaultId) {
2211       return TRUE;
2212     }
2213   }
2214 
2215   return FALSE;
2216 }
2217 
2218 EFI_VFR_RETURN_CODE
GetDefaultId(IN CHAR8 * RefName,OUT UINT16 * DefaultId)2219 CVfrDefaultStore::GetDefaultId (
2220   IN  CHAR8           *RefName,
2221   OUT UINT16          *DefaultId
2222   )
2223 {
2224   SVfrDefaultStoreNode *pTmp = NULL;
2225 
2226   if (DefaultId == NULL) {
2227     return VFR_RETURN_FATAL_ERROR;
2228   }
2229 
2230   for (pTmp = mDefaultStoreList; pTmp != NULL; pTmp = pTmp->mNext) {
2231     if (strcmp (pTmp->mRefName, RefName) == 0) {
2232       *DefaultId = pTmp->mDefaultId;
2233       return VFR_RETURN_SUCCESS;
2234     }
2235   }
2236 
2237   return VFR_RETURN_UNDEFINED;
2238 }
2239 
2240 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)2241 CVfrDefaultStore::BufferVarStoreAltConfigAdd (
2242   IN EFI_VARSTORE_ID    DefaultId,
2243   IN EFI_VARSTORE_INFO  &Info,
2244   IN CHAR8              *VarStoreName,
2245   IN EFI_GUID           *VarStoreGuid,
2246   IN UINT8              Type,
2247   IN EFI_IFR_TYPE_VALUE Value
2248   )
2249 {
2250   SVfrDefaultStoreNode  *pNode = NULL;
2251   CHAR8                 NewAltCfg[2 * 2 * sizeof (UINT16) + 1] = {0,};
2252   INTN                  Returnvalue = 0;
2253 
2254   if (VarStoreName == NULL) {
2255     return VFR_RETURN_FATAL_ERROR;
2256   }
2257 
2258   for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) {
2259     if (pNode->mDefaultId == DefaultId) {
2260       break;
2261     }
2262   }
2263 
2264   if (pNode == NULL) {
2265     return VFR_RETURN_UNDEFINED;
2266   }
2267 
2268   gCVfrBufferConfig.Open ();
2269 
2270   sprintf (NewAltCfg, "%04x", pNode->mDefaultId);
2271   if ((Returnvalue = gCVfrBufferConfig.Select(VarStoreName, VarStoreGuid)) == 0) {
2272     if ((Returnvalue = gCVfrBufferConfig.Write ('a', VarStoreName, VarStoreGuid, NewAltCfg, Type, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value)) != 0) {
2273       goto WriteError;
2274     }
2275   }
2276 
2277   gCVfrBufferConfig.Close ();
2278 
2279   return VFR_RETURN_SUCCESS;
2280 
2281 WriteError:
2282   gCVfrBufferConfig.Close ();
2283   return (EFI_VFR_RETURN_CODE)Returnvalue;
2284 }
2285 
SVfrRuleNode(IN CHAR8 * RuleName,IN UINT8 RuleId)2286 SVfrRuleNode::SVfrRuleNode (
2287   IN CHAR8        *RuleName,
2288   IN UINT8       RuleId
2289   )
2290 {
2291   if (RuleName != NULL) {
2292     mRuleName = new CHAR8[strlen (RuleName) + 1];
2293     strcpy (mRuleName, RuleName);
2294   } else {
2295     mRuleName = NULL;
2296   }
2297 
2298   mNext       = NULL;
2299   mRuleId     = RuleId;
2300 }
2301 
~SVfrRuleNode(VOID)2302 SVfrRuleNode::~SVfrRuleNode (
2303   VOID
2304   )
2305 {
2306   if (mRuleName != NULL) {
2307     delete[] mRuleName;
2308   }
2309 }
2310 
CVfrRulesDB()2311 CVfrRulesDB::CVfrRulesDB ()
2312 {
2313   mRuleList   = NULL;
2314   mFreeRuleId = EFI_VARSTORE_ID_START;
2315 }
2316 
~CVfrRulesDB()2317 CVfrRulesDB::~CVfrRulesDB ()
2318 {
2319   SVfrRuleNode *pNode;
2320 
2321   while(mRuleList != NULL) {
2322     pNode = mRuleList;
2323     mRuleList = mRuleList->mNext;
2324     delete pNode;
2325   }
2326 }
2327 
2328 VOID
RegisterRule(IN CHAR8 * RuleName)2329 CVfrRulesDB::RegisterRule (
2330   IN CHAR8  *RuleName
2331   )
2332 {
2333   SVfrRuleNode *pNew;
2334 
2335   if (RuleName == NULL) {
2336     return ;
2337   }
2338 
2339   if ((pNew = new SVfrRuleNode (RuleName, mFreeRuleId)) == NULL) {
2340     return ;
2341   }
2342 
2343   mFreeRuleId++;
2344 
2345   pNew->mNext = mRuleList;
2346   mRuleList   = pNew;
2347 }
2348 
2349 UINT8
GetRuleId(IN CHAR8 * RuleName)2350 CVfrRulesDB::GetRuleId (
2351   IN CHAR8  *RuleName
2352   )
2353 {
2354   SVfrRuleNode *pNode;
2355 
2356   if (RuleName == NULL) {
2357     return EFI_RULE_ID_INVALID;
2358   }
2359 
2360   for (pNode = mRuleList; pNode != NULL; pNode = pNode->mNext) {
2361     if (strcmp (pNode->mRuleName, RuleName) == 0) {
2362       return pNode->mRuleId;
2363     }
2364   }
2365 
2366   return EFI_RULE_ID_INVALID;
2367 }
2368 
2369 CVfrRulesDB gCVfrRulesDB;
2370 
EFI_VARSTORE_INFO(VOID)2371 EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
2372   VOID
2373   )
2374 {
2375   mVarStoreId      = EFI_VARSTORE_ID_INVALID;
2376   mInfo.mVarName   = EFI_STRING_ID_INVALID;
2377   mInfo.mVarOffset = EFI_VAROFFSET_INVALID;
2378   mVarType         = EFI_IFR_TYPE_OTHER;
2379   mVarTotalSize    = 0;
2380 }
2381 
EFI_VARSTORE_INFO(IN EFI_VARSTORE_INFO & Info)2382 EFI_VARSTORE_INFO::EFI_VARSTORE_INFO (
2383   IN EFI_VARSTORE_INFO &Info
2384   )
2385 {
2386   mVarStoreId      = Info.mVarStoreId;
2387   mInfo.mVarName   = Info.mInfo.mVarName;
2388   mInfo.mVarOffset = Info.mInfo.mVarOffset;
2389   mVarType         = Info.mVarType;
2390   mVarTotalSize    = Info.mVarTotalSize;
2391 }
2392 
2393 EFI_VARSTORE_INFO&
operator =(IN CONST EFI_VARSTORE_INFO & Info)2394 EFI_VARSTORE_INFO::operator= (
2395   IN CONST EFI_VARSTORE_INFO &Info
2396   )
2397 {
2398   if (this != &Info) {
2399     mVarStoreId      = Info.mVarStoreId;
2400     mInfo.mVarName   = Info.mInfo.mVarName;
2401     mInfo.mVarOffset = Info.mInfo.mVarOffset;
2402     mVarType         = Info.mVarType;
2403     mVarTotalSize    = Info.mVarTotalSize;
2404   }
2405 
2406   return *this;
2407 }
2408 
2409 BOOLEAN
operator ==(IN EFI_VARSTORE_INFO * Info)2410 EFI_VARSTORE_INFO::operator == (
2411   IN EFI_VARSTORE_INFO  *Info
2412   )
2413 {
2414   if ((mVarStoreId == Info->mVarStoreId) &&
2415   	  (mInfo.mVarName == Info->mInfo.mVarName) &&
2416       (mInfo.mVarOffset == Info->mInfo.mVarOffset) &&
2417       (mVarType == Info->mVarType) &&
2418       (mVarTotalSize == Info->mVarTotalSize)) {
2419     return TRUE;
2420   }
2421 
2422   return FALSE;
2423 }
2424 
BufferVarStoreFieldInfoNode(IN EFI_VARSTORE_INFO * Info)2425 BufferVarStoreFieldInfoNode::BufferVarStoreFieldInfoNode(
2426   IN EFI_VARSTORE_INFO  *Info
2427   )
2428 {
2429   mVarStoreInfo.mVarType               = Info->mVarType;
2430   mVarStoreInfo.mVarTotalSize          = Info->mVarTotalSize;
2431   mVarStoreInfo.mInfo.mVarOffset       = Info->mInfo.mVarOffset;
2432   mVarStoreInfo.mVarStoreId            = Info->mVarStoreId;
2433   mNext = NULL;
2434 }
2435 
~BufferVarStoreFieldInfoNode()2436 BufferVarStoreFieldInfoNode::~BufferVarStoreFieldInfoNode ()
2437 {
2438   mVarStoreInfo.mVarType               = EFI_IFR_TYPE_OTHER;
2439   mVarStoreInfo.mVarTotalSize          = 0;
2440   mVarStoreInfo.mInfo.mVarOffset       = EFI_VAROFFSET_INVALID;
2441   mVarStoreInfo.mVarStoreId            = EFI_VARSTORE_ID_INVALID;
2442   mNext = NULL;
2443 }
2444 
2445 static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo;
2446 
2447 EFI_QUESTION_ID
GetFreeQuestionId(VOID)2448 CVfrQuestionDB::GetFreeQuestionId (
2449   VOID
2450   )
2451 {
2452   UINT32  Index, Mask, Offset;
2453 
2454   for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
2455     if (mFreeQIdBitMap[Index] != 0xFFFFFFFF) {
2456       break;
2457     }
2458   }
2459 
2460   if (Index == EFI_FREE_QUESTION_ID_BITMAP_SIZE) {
2461     return EFI_QUESTION_ID_INVALID;
2462   }
2463 
2464   for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
2465     if ((mFreeQIdBitMap[Index] & Mask) == 0) {
2466       mFreeQIdBitMap[Index] |= Mask;
2467       return (EFI_QUESTION_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset);
2468     }
2469   }
2470 
2471   return EFI_QUESTION_ID_INVALID;
2472 }
2473 
2474 BOOLEAN
ChekQuestionIdFree(IN EFI_QUESTION_ID QId)2475 CVfrQuestionDB::ChekQuestionIdFree (
2476   IN EFI_QUESTION_ID QId
2477   )
2478 {
2479   UINT32 Index  = (QId / EFI_BITS_PER_UINT32);
2480   UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
2481 
2482   return (mFreeQIdBitMap[Index] & (0x80000000 >> Offset)) == 0;
2483 }
2484 
2485 VOID
MarkQuestionIdUsed(IN EFI_QUESTION_ID QId)2486 CVfrQuestionDB::MarkQuestionIdUsed (
2487   IN EFI_QUESTION_ID QId
2488   )
2489 {
2490   UINT32 Index  = (QId / EFI_BITS_PER_UINT32);
2491   UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
2492 
2493   mFreeQIdBitMap[Index] |= (0x80000000 >> Offset);
2494 }
2495 
2496 VOID
MarkQuestionIdUnused(IN EFI_QUESTION_ID QId)2497 CVfrQuestionDB::MarkQuestionIdUnused (
2498   IN EFI_QUESTION_ID QId
2499   )
2500 {
2501   UINT32 Index  = (QId / EFI_BITS_PER_UINT32);
2502   UINT32 Offset = (QId % EFI_BITS_PER_UINT32);
2503 
2504   mFreeQIdBitMap[Index] &= ~(0x80000000 >> Offset);
2505 }
2506 
SVfrQuestionNode(IN CHAR8 * Name,IN CHAR8 * VarIdStr,IN UINT32 BitMask)2507 SVfrQuestionNode::SVfrQuestionNode (
2508   IN CHAR8  *Name,
2509   IN CHAR8  *VarIdStr,
2510   IN UINT32 BitMask
2511   )
2512 {
2513   mName       = NULL;
2514   mVarIdStr   = NULL;
2515   mQuestionId = EFI_QUESTION_ID_INVALID;
2516   mBitMask    = BitMask;
2517   mNext       = NULL;
2518   mQtype      = QUESTION_NORMAL;
2519 
2520   if (Name == NULL) {
2521     mName = new CHAR8[strlen ("$DEFAULT") + 1];
2522     strcpy (mName, "$DEFAULT");
2523   } else {
2524     mName = new CHAR8[strlen (Name) + 1];
2525     strcpy (mName, Name);
2526   }
2527 
2528   if (VarIdStr != NULL) {
2529     mVarIdStr = new CHAR8[strlen (VarIdStr) + 1];
2530     strcpy (mVarIdStr, VarIdStr);
2531   } else {
2532     mVarIdStr = new CHAR8[strlen ("$") + 1];
2533     strcpy (mVarIdStr, "$");
2534   }
2535 }
2536 
~SVfrQuestionNode(VOID)2537 SVfrQuestionNode::~SVfrQuestionNode (
2538   VOID
2539   )
2540 {
2541   if (mName != NULL) {
2542     delete[] mName;
2543   }
2544 
2545   if (mVarIdStr != NULL) {
2546     delete[] mVarIdStr;
2547   }
2548 }
2549 
CVfrQuestionDB()2550 CVfrQuestionDB::CVfrQuestionDB ()
2551 {
2552   UINT32 Index;
2553 
2554   for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
2555     mFreeQIdBitMap[Index] = 0;
2556   }
2557 
2558   // Question ID 0 is reserved.
2559   mFreeQIdBitMap[0] = 0x80000000;
2560   mQuestionList     = NULL;
2561 }
2562 
~CVfrQuestionDB()2563 CVfrQuestionDB::~CVfrQuestionDB ()
2564 {
2565   SVfrQuestionNode     *pNode;
2566 
2567   while (mQuestionList != NULL) {
2568     pNode = mQuestionList;
2569     mQuestionList = mQuestionList->mNext;
2570     delete pNode;
2571   }
2572 }
2573 
2574 //
2575 // Reset to init state
2576 //
2577 VOID
ResetInit(IN VOID)2578 CVfrQuestionDB::ResetInit(
2579   IN VOID
2580   )
2581 {
2582   UINT32               Index;
2583   SVfrQuestionNode     *pNode;
2584 
2585   while (mQuestionList != NULL) {
2586     pNode = mQuestionList;
2587     mQuestionList = mQuestionList->mNext;
2588     delete pNode;
2589   }
2590 
2591   for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) {
2592     mFreeQIdBitMap[Index] = 0;
2593   }
2594 
2595   // Question ID 0 is reserved.
2596   mFreeQIdBitMap[0] = 0x80000000;
2597   mQuestionList     = NULL;
2598 }
2599 
2600 VOID
PrintAllQuestion(VOID)2601 CVfrQuestionDB::PrintAllQuestion (
2602   VOID
2603   )
2604 {
2605   SVfrQuestionNode *pNode = NULL;
2606 
2607   for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
2608     printf ("Question VarId is %s and QuesitonId is 0x%x\n", pNode->mVarIdStr, pNode->mQuestionId);
2609   }
2610 }
2611 
2612 EFI_VFR_RETURN_CODE
RegisterQuestion(IN CHAR8 * Name,IN CHAR8 * VarIdStr,IN OUT EFI_QUESTION_ID & QuestionId)2613 CVfrQuestionDB::RegisterQuestion (
2614   IN     CHAR8             *Name,
2615   IN     CHAR8             *VarIdStr,
2616   IN OUT EFI_QUESTION_ID   &QuestionId
2617   )
2618 {
2619   SVfrQuestionNode *pNode = NULL;
2620 
2621   if ((Name != NULL) && (FindQuestion(Name) == VFR_RETURN_SUCCESS)) {
2622     return VFR_RETURN_REDEFINED;
2623   }
2624 
2625   if ((pNode = new SVfrQuestionNode (Name, VarIdStr)) == NULL) {
2626     return VFR_RETURN_OUT_FOR_RESOURCES;
2627   }
2628 
2629   if (QuestionId == EFI_QUESTION_ID_INVALID) {
2630     QuestionId = GetFreeQuestionId ();
2631   } else {
2632     //
2633     // For Framework Vfr, don't check question ID conflict.
2634     //
2635     if (!VfrCompatibleMode && ChekQuestionIdFree (QuestionId) == FALSE) {
2636       delete pNode;
2637       return VFR_RETURN_QUESTIONID_REDEFINED;
2638     }
2639     MarkQuestionIdUsed (QuestionId);
2640   }
2641   pNode->mQuestionId = QuestionId;
2642 
2643   pNode->mNext       = mQuestionList;
2644   mQuestionList      = pNode;
2645 
2646   gCFormPkg.DoPendingAssign (VarIdStr, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2647 
2648   return VFR_RETURN_SUCCESS;
2649 }
2650 
2651 VOID
RegisterOldDateQuestion(IN CHAR8 * YearVarId,IN CHAR8 * MonthVarId,IN CHAR8 * DayVarId,IN OUT EFI_QUESTION_ID & QuestionId)2652 CVfrQuestionDB::RegisterOldDateQuestion (
2653   IN     CHAR8            *YearVarId,
2654   IN     CHAR8            *MonthVarId,
2655   IN     CHAR8            *DayVarId,
2656   IN OUT EFI_QUESTION_ID &QuestionId
2657   )
2658 {
2659   SVfrQuestionNode *pNode[3] = {NULL, };
2660   UINT32           Index;
2661 
2662   if ((YearVarId == NULL) || (MonthVarId == NULL) || (DayVarId == NULL)) {
2663     return;
2664   }
2665 
2666   if ((pNode[0] = new SVfrQuestionNode (NULL, YearVarId, DATE_YEAR_BITMASK)) == NULL) {
2667     goto Err;
2668   }
2669   if ((pNode[1] = new SVfrQuestionNode (NULL, MonthVarId, DATE_MONTH_BITMASK)) == NULL) {
2670     goto Err;
2671   }
2672   if ((pNode[2] = new SVfrQuestionNode (NULL, DayVarId, DATE_DAY_BITMASK)) == NULL) {
2673     goto Err;
2674   }
2675 
2676   if (QuestionId == EFI_QUESTION_ID_INVALID) {
2677     QuestionId = GetFreeQuestionId ();
2678   } else {
2679     if (ChekQuestionIdFree (QuestionId) == FALSE) {
2680       goto Err;
2681     }
2682     MarkQuestionIdUsed (QuestionId);
2683   }
2684 
2685   pNode[0]->mQuestionId = QuestionId;
2686   pNode[1]->mQuestionId = QuestionId;
2687   pNode[2]->mQuestionId = QuestionId;
2688   pNode[0]->mQtype      = QUESTION_DATE;
2689   pNode[1]->mQtype      = QUESTION_DATE;
2690   pNode[2]->mQtype      = QUESTION_DATE;
2691   pNode[0]->mNext       = pNode[1];
2692   pNode[1]->mNext       = pNode[2];
2693   pNode[2]->mNext       = mQuestionList;
2694   mQuestionList         = pNode[0];
2695 
2696   gCFormPkg.DoPendingAssign (YearVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2697   gCFormPkg.DoPendingAssign (MonthVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2698   gCFormPkg.DoPendingAssign (DayVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2699 
2700   return;
2701 
2702 Err:
2703   for (Index = 0; Index < 3; Index++) {
2704     if (pNode[Index] != NULL) {
2705       delete pNode[Index];
2706     }
2707   }
2708   QuestionId = EFI_QUESTION_ID_INVALID;
2709 }
2710 
2711 VOID
RegisterNewDateQuestion(IN CHAR8 * Name,IN CHAR8 * BaseVarId,IN OUT EFI_QUESTION_ID & QuestionId)2712 CVfrQuestionDB::RegisterNewDateQuestion (
2713   IN     CHAR8            *Name,
2714   IN     CHAR8            *BaseVarId,
2715   IN OUT EFI_QUESTION_ID &QuestionId
2716   )
2717 {
2718   SVfrQuestionNode     *pNode[3] = {NULL, };
2719   UINT32               Len;
2720   CHAR8                *VarIdStr[3] = {NULL, };
2721   CHAR8                 Index;
2722 
2723   if (BaseVarId == NULL && Name == NULL) {
2724     if (QuestionId == EFI_QUESTION_ID_INVALID) {
2725       QuestionId = GetFreeQuestionId ();
2726     } else {
2727       if (ChekQuestionIdFree (QuestionId) == FALSE) {
2728         goto Err;
2729       }
2730       MarkQuestionIdUsed (QuestionId);
2731     }
2732     return;
2733   }
2734 
2735   if (BaseVarId != NULL) {
2736     Len = strlen (BaseVarId);
2737 
2738     VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1];
2739     if (VarIdStr[0] != NULL) {
2740       strcpy (VarIdStr[0], BaseVarId);
2741       strcat (VarIdStr[0], ".Year");
2742     }
2743     VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1];
2744     if (VarIdStr[1] != NULL) {
2745       strcpy (VarIdStr[1], BaseVarId);
2746       strcat (VarIdStr[1], ".Month");
2747     }
2748     VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1];
2749     if (VarIdStr[2] != NULL) {
2750       strcpy (VarIdStr[2], BaseVarId);
2751       strcat (VarIdStr[2], ".Day");
2752     }
2753   } else {
2754     Len = strlen (Name);
2755 
2756     VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1];
2757     if (VarIdStr[0] != NULL) {
2758       strcpy (VarIdStr[0], Name);
2759       strcat (VarIdStr[0], ".Year");
2760     }
2761     VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1];
2762     if (VarIdStr[1] != NULL) {
2763       strcpy (VarIdStr[1], Name);
2764       strcat (VarIdStr[1], ".Month");
2765     }
2766     VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1];
2767     if (VarIdStr[2] != NULL) {
2768       strcpy (VarIdStr[2], Name);
2769       strcat (VarIdStr[2], ".Day");
2770     }
2771   }
2772 
2773   if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], DATE_YEAR_BITMASK)) == NULL) {
2774     goto Err;
2775   }
2776   if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], DATE_MONTH_BITMASK)) == NULL) {
2777     goto Err;
2778   }
2779   if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], DATE_DAY_BITMASK)) == NULL) {
2780     goto Err;
2781   }
2782 
2783   if (QuestionId == EFI_QUESTION_ID_INVALID) {
2784     QuestionId = GetFreeQuestionId ();
2785   } else {
2786     if (ChekQuestionIdFree (QuestionId) == FALSE) {
2787       goto Err;
2788     }
2789     MarkQuestionIdUsed (QuestionId);
2790   }
2791 
2792   pNode[0]->mQuestionId = QuestionId;
2793   pNode[1]->mQuestionId = QuestionId;
2794   pNode[2]->mQuestionId = QuestionId;
2795   pNode[0]->mQtype      = QUESTION_DATE;
2796   pNode[1]->mQtype      = QUESTION_DATE;
2797   pNode[2]->mQtype      = QUESTION_DATE;
2798   pNode[0]->mNext       = pNode[1];
2799   pNode[1]->mNext       = pNode[2];
2800   pNode[2]->mNext       = mQuestionList;
2801   mQuestionList         = pNode[0];
2802 
2803   for (Index = 0; Index < 3; Index++) {
2804     if (VarIdStr[Index] != NULL) {
2805       delete VarIdStr[Index];
2806     }
2807   }
2808 
2809   gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2810   gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2811   gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2812 
2813   return;
2814 
2815 Err:
2816   for (Index = 0; Index < 3; Index++) {
2817     if (pNode[Index] != NULL) {
2818       delete pNode[Index];
2819     }
2820 
2821     if (VarIdStr[Index] != NULL) {
2822       delete VarIdStr[Index];
2823     }
2824   }
2825 }
2826 
2827 VOID
RegisterOldTimeQuestion(IN CHAR8 * HourVarId,IN CHAR8 * MinuteVarId,IN CHAR8 * SecondVarId,IN OUT EFI_QUESTION_ID & QuestionId)2828 CVfrQuestionDB::RegisterOldTimeQuestion (
2829   IN     CHAR8            *HourVarId,
2830   IN     CHAR8            *MinuteVarId,
2831   IN     CHAR8            *SecondVarId,
2832   IN OUT EFI_QUESTION_ID &QuestionId
2833   )
2834 {
2835   SVfrQuestionNode *pNode[3] = {NULL, };
2836   UINT32           Index;
2837 
2838   if ((HourVarId == NULL) || (MinuteVarId == NULL) || (SecondVarId == NULL)) {
2839     return;
2840   }
2841 
2842   if ((pNode[0] = new SVfrQuestionNode (NULL, HourVarId, TIME_HOUR_BITMASK)) == NULL) {
2843     goto Err;
2844   }
2845   if ((pNode[1] = new SVfrQuestionNode (NULL, MinuteVarId, TIME_MINUTE_BITMASK)) == NULL) {
2846     goto Err;
2847   }
2848   if ((pNode[2] = new SVfrQuestionNode (NULL, SecondVarId, TIME_SECOND_BITMASK)) == NULL) {
2849     goto Err;
2850   }
2851 
2852   if (QuestionId == EFI_QUESTION_ID_INVALID) {
2853     QuestionId = GetFreeQuestionId ();
2854   } else {
2855     if (ChekQuestionIdFree (QuestionId) == FALSE) {
2856       goto Err;
2857     }
2858     MarkQuestionIdUsed (QuestionId);
2859   }
2860 
2861   pNode[0]->mQuestionId = QuestionId;
2862   pNode[1]->mQuestionId = QuestionId;
2863   pNode[2]->mQuestionId = QuestionId;
2864   pNode[0]->mQtype      = QUESTION_TIME;
2865   pNode[1]->mQtype      = QUESTION_TIME;
2866   pNode[2]->mQtype      = QUESTION_TIME;
2867   pNode[0]->mNext       = pNode[1];
2868   pNode[1]->mNext       = pNode[2];
2869   pNode[2]->mNext       = mQuestionList;
2870   mQuestionList         = pNode[0];
2871 
2872   gCFormPkg.DoPendingAssign (HourVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2873   gCFormPkg.DoPendingAssign (MinuteVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2874   gCFormPkg.DoPendingAssign (SecondVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2875 
2876   return;
2877 
2878 Err:
2879   for (Index = 0; Index < 3; Index++) {
2880     if (pNode[Index] != NULL) {
2881       delete pNode[Index];
2882     }
2883   }
2884   QuestionId = EFI_QUESTION_ID_INVALID;
2885 }
2886 
2887 VOID
RegisterNewTimeQuestion(IN CHAR8 * Name,IN CHAR8 * BaseVarId,IN OUT EFI_QUESTION_ID & QuestionId)2888 CVfrQuestionDB::RegisterNewTimeQuestion (
2889   IN     CHAR8           *Name,
2890   IN     CHAR8           *BaseVarId,
2891   IN OUT EFI_QUESTION_ID &QuestionId
2892   )
2893 {
2894   SVfrQuestionNode     *pNode[3] = {NULL, };
2895   UINT32               Len;
2896   CHAR8                *VarIdStr[3] = {NULL, };
2897   CHAR8                 Index;
2898 
2899   if (BaseVarId == NULL && Name == NULL) {
2900     if (QuestionId == EFI_QUESTION_ID_INVALID) {
2901       QuestionId = GetFreeQuestionId ();
2902     } else {
2903       if (ChekQuestionIdFree (QuestionId) == FALSE) {
2904         goto Err;
2905       }
2906       MarkQuestionIdUsed (QuestionId);
2907     }
2908     return;
2909   }
2910 
2911   if (BaseVarId != NULL) {
2912     Len = strlen (BaseVarId);
2913 
2914     VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1];
2915     if (VarIdStr[0] != NULL) {
2916       strcpy (VarIdStr[0], BaseVarId);
2917       strcat (VarIdStr[0], ".Hour");
2918     }
2919     VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1];
2920     if (VarIdStr[1] != NULL) {
2921       strcpy (VarIdStr[1], BaseVarId);
2922       strcat (VarIdStr[1], ".Minute");
2923     }
2924     VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1];
2925     if (VarIdStr[2] != NULL) {
2926       strcpy (VarIdStr[2], BaseVarId);
2927       strcat (VarIdStr[2], ".Second");
2928     }
2929   } else {
2930     Len = strlen (Name);
2931 
2932     VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1];
2933     if (VarIdStr[0] != NULL) {
2934       strcpy (VarIdStr[0], Name);
2935       strcat (VarIdStr[0], ".Hour");
2936     }
2937     VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1];
2938     if (VarIdStr[1] != NULL) {
2939       strcpy (VarIdStr[1], Name);
2940       strcat (VarIdStr[1], ".Minute");
2941     }
2942     VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1];
2943     if (VarIdStr[2] != NULL) {
2944       strcpy (VarIdStr[2], Name);
2945       strcat (VarIdStr[2], ".Second");
2946     }
2947   }
2948 
2949   if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], TIME_HOUR_BITMASK)) == NULL) {
2950     goto Err;
2951   }
2952   if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], TIME_MINUTE_BITMASK)) == NULL) {
2953     goto Err;
2954   }
2955   if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], TIME_SECOND_BITMASK)) == NULL) {
2956     goto Err;
2957   }
2958 
2959   if (QuestionId == EFI_QUESTION_ID_INVALID) {
2960     QuestionId = GetFreeQuestionId ();
2961   } else {
2962     if (ChekQuestionIdFree (QuestionId) == FALSE) {
2963       goto Err;
2964     }
2965     MarkQuestionIdUsed (QuestionId);
2966   }
2967 
2968   pNode[0]->mQuestionId = QuestionId;
2969   pNode[1]->mQuestionId = QuestionId;
2970   pNode[2]->mQuestionId = QuestionId;
2971   pNode[0]->mQtype      = QUESTION_TIME;
2972   pNode[1]->mQtype      = QUESTION_TIME;
2973   pNode[2]->mQtype      = QUESTION_TIME;
2974   pNode[0]->mNext       = pNode[1];
2975   pNode[1]->mNext       = pNode[2];
2976   pNode[2]->mNext       = mQuestionList;
2977   mQuestionList         = pNode[0];
2978 
2979   for (Index = 0; Index < 3; Index++) {
2980     if (VarIdStr[Index] != NULL) {
2981       delete VarIdStr[Index];
2982     }
2983   }
2984 
2985   gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2986   gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2987   gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
2988 
2989   return;
2990 
2991 Err:
2992   for (Index = 0; Index < 3; Index++) {
2993     if (pNode[Index] != NULL) {
2994       delete pNode[Index];
2995     }
2996 
2997     if (VarIdStr[Index] != NULL) {
2998       delete VarIdStr[Index];
2999     }
3000   }
3001 }
3002 
3003 VOID
RegisterRefQuestion(IN CHAR8 * Name,IN CHAR8 * BaseVarId,IN OUT EFI_QUESTION_ID & QuestionId)3004 CVfrQuestionDB::RegisterRefQuestion (
3005   IN     CHAR8           *Name,
3006   IN     CHAR8           *BaseVarId,
3007   IN OUT EFI_QUESTION_ID &QuestionId
3008   )
3009 {
3010   SVfrQuestionNode     *pNode[4] = {NULL, };
3011   UINT32               Len;
3012   CHAR8                *VarIdStr[4] = {NULL, };
3013   CHAR8                 Index;
3014 
3015   if (BaseVarId == NULL && Name == NULL) {
3016     return;
3017   }
3018 
3019   if (BaseVarId != NULL) {
3020     Len = strlen (BaseVarId);
3021 
3022     VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
3023     if (VarIdStr[0] != NULL) {
3024       strcpy (VarIdStr[0], BaseVarId);
3025       strcat (VarIdStr[0], ".QuestionId");
3026     }
3027     VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
3028     if (VarIdStr[1] != NULL) {
3029       strcpy (VarIdStr[1], BaseVarId);
3030       strcat (VarIdStr[1], ".FormId");
3031     }
3032     VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
3033     if (VarIdStr[2] != NULL) {
3034       strcpy (VarIdStr[2], BaseVarId);
3035       strcat (VarIdStr[2], ".FormSetGuid");
3036     }
3037     VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
3038     if (VarIdStr[3] != NULL) {
3039       strcpy (VarIdStr[3], BaseVarId);
3040       strcat (VarIdStr[3], ".DevicePath");
3041     }
3042   } else {
3043     Len = strlen (Name);
3044 
3045     VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1];
3046     if (VarIdStr[0] != NULL) {
3047       strcpy (VarIdStr[0], Name);
3048       strcat (VarIdStr[0], ".QuestionId");
3049     }
3050     VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1];
3051     if (VarIdStr[1] != NULL) {
3052       strcpy (VarIdStr[1], Name);
3053       strcat (VarIdStr[1], ".FormId");
3054     }
3055     VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1];
3056     if (VarIdStr[2] != NULL) {
3057       strcpy (VarIdStr[2], Name);
3058       strcat (VarIdStr[2], ".FormSetGuid");
3059     }
3060     VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1];
3061     if (VarIdStr[3] != NULL) {
3062       strcpy (VarIdStr[3], Name);
3063       strcat (VarIdStr[3], ".DevicePath");
3064     }
3065   }
3066 
3067   if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0])) == NULL) {
3068     goto Err;
3069   }
3070   if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1])) == NULL) {
3071     goto Err;
3072   }
3073   if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2])) == NULL) {
3074     goto Err;
3075   }
3076   if ((pNode[3] = new SVfrQuestionNode (Name, VarIdStr[3])) == NULL) {
3077     goto Err;
3078   }
3079 
3080   if (QuestionId == EFI_QUESTION_ID_INVALID) {
3081     QuestionId = GetFreeQuestionId ();
3082   } else {
3083     if (ChekQuestionIdFree (QuestionId) == FALSE) {
3084       goto Err;
3085     }
3086     MarkQuestionIdUsed (QuestionId);
3087   }
3088 
3089   pNode[0]->mQuestionId = QuestionId;
3090   pNode[1]->mQuestionId = QuestionId;
3091   pNode[2]->mQuestionId = QuestionId;
3092   pNode[3]->mQuestionId = QuestionId;
3093   pNode[0]->mQtype      = QUESTION_REF;
3094   pNode[1]->mQtype      = QUESTION_REF;
3095   pNode[2]->mQtype      = QUESTION_REF;
3096   pNode[3]->mQtype      = QUESTION_REF;
3097   pNode[0]->mNext       = pNode[1];
3098   pNode[1]->mNext       = pNode[2];
3099   pNode[2]->mNext       = pNode[3];
3100   pNode[3]->mNext       = mQuestionList;
3101   mQuestionList         = pNode[0];
3102 
3103   gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
3104   gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
3105   gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
3106   gCFormPkg.DoPendingAssign (VarIdStr[3], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID));
3107 
3108   return;
3109 
3110   Err:
3111   for (Index = 0; Index < 4; Index++) {
3112     if (pNode[Index] != NULL) {
3113       delete pNode[Index];
3114     }
3115 
3116     if (VarIdStr[Index] != NULL) {
3117       delete VarIdStr[Index];
3118     }
3119   }
3120 }
3121 
3122 EFI_VFR_RETURN_CODE
UpdateQuestionId(IN EFI_QUESTION_ID QId,IN EFI_QUESTION_ID NewQId)3123 CVfrQuestionDB::UpdateQuestionId (
3124   IN EFI_QUESTION_ID   QId,
3125   IN EFI_QUESTION_ID   NewQId
3126   )
3127 {
3128   SVfrQuestionNode *pNode = NULL;
3129 
3130   if (QId == NewQId) {
3131     // don't update
3132     return VFR_RETURN_SUCCESS;
3133   }
3134 
3135   //
3136   // For Framework Vfr, don't check question ID conflict.
3137   //
3138   if (!VfrCompatibleMode && ChekQuestionIdFree (NewQId) == FALSE) {
3139     return VFR_RETURN_REDEFINED;
3140   }
3141 
3142   for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3143     if (pNode->mQuestionId == QId) {
3144       break;
3145     }
3146   }
3147 
3148   if (pNode == NULL) {
3149     return VFR_RETURN_UNDEFINED;
3150   }
3151 
3152   MarkQuestionIdUnused (QId);
3153   pNode->mQuestionId = NewQId;
3154   MarkQuestionIdUsed (NewQId);
3155 
3156   gCFormPkg.DoPendingAssign (pNode->mVarIdStr, (VOID *)&NewQId, sizeof(EFI_QUESTION_ID));
3157 
3158   return VFR_RETURN_SUCCESS;
3159 }
3160 
3161 VOID
GetQuestionId(IN CHAR8 * Name,IN CHAR8 * VarIdStr,OUT EFI_QUESTION_ID & QuestionId,OUT UINT32 & BitMask,OUT EFI_QUESION_TYPE * QType)3162 CVfrQuestionDB::GetQuestionId (
3163   IN  CHAR8             *Name,
3164   IN  CHAR8             *VarIdStr,
3165   OUT EFI_QUESTION_ID   &QuestionId,
3166   OUT UINT32            &BitMask,
3167   OUT EFI_QUESION_TYPE  *QType
3168   )
3169 {
3170   SVfrQuestionNode *pNode;
3171 
3172   QuestionId = EFI_QUESTION_ID_INVALID;
3173   BitMask    = 0x00000000;
3174   if (QType != NULL) {
3175     *QType = QUESTION_NORMAL;
3176   }
3177 
3178   if ((Name == NULL) && (VarIdStr == NULL)) {
3179     return ;
3180   }
3181 
3182   for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3183     if (Name != NULL) {
3184       if (strcmp (pNode->mName, Name) != 0) {
3185         continue;
3186       }
3187     }
3188 
3189     if (VarIdStr != NULL) {
3190       if (strcmp (pNode->mVarIdStr, VarIdStr) != 0) {
3191         continue;
3192       }
3193   	}
3194 
3195     QuestionId = pNode->mQuestionId;
3196     BitMask    = pNode->mBitMask;
3197     if (QType != NULL) {
3198       *QType     = pNode->mQtype;
3199     }
3200     break;
3201   }
3202 
3203   return ;
3204 }
3205 
3206 EFI_VFR_RETURN_CODE
FindQuestion(IN EFI_QUESTION_ID QuestionId)3207 CVfrQuestionDB::FindQuestion (
3208   IN EFI_QUESTION_ID QuestionId
3209   )
3210 {
3211   SVfrQuestionNode *pNode;
3212 
3213   if (QuestionId == EFI_QUESTION_ID_INVALID) {
3214     return VFR_RETURN_INVALID_PARAMETER;
3215   }
3216 
3217   for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3218     if (pNode->mQuestionId == QuestionId) {
3219       return VFR_RETURN_SUCCESS;
3220     }
3221   }
3222 
3223   return VFR_RETURN_UNDEFINED;
3224 }
3225 
3226 EFI_VFR_RETURN_CODE
FindQuestion(IN CHAR8 * Name)3227 CVfrQuestionDB::FindQuestion (
3228   IN CHAR8 *Name
3229   )
3230 {
3231   SVfrQuestionNode *pNode;
3232 
3233   if (Name == NULL) {
3234     return VFR_RETURN_FATAL_ERROR;
3235   }
3236 
3237   for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) {
3238     if (strcmp (pNode->mName, Name) == 0) {
3239       return VFR_RETURN_SUCCESS;
3240     }
3241   }
3242 
3243   return VFR_RETURN_UNDEFINED;
3244 }
3245 
CVfrStringDB()3246 CVfrStringDB::CVfrStringDB ()
3247 {
3248   mStringFileName = NULL;
3249 }
3250 
~CVfrStringDB()3251 CVfrStringDB::~CVfrStringDB ()
3252 {
3253   if (mStringFileName != NULL) {
3254     delete mStringFileName;
3255   }
3256   mStringFileName = NULL;
3257 }
3258 
3259 
3260 VOID
SetStringFileName(IN CHAR8 * StringFileName)3261 CVfrStringDB::SetStringFileName(IN CHAR8 *StringFileName)
3262 {
3263   UINT32 FileLen = 0;
3264 
3265   if (StringFileName == NULL) {
3266     return;
3267   }
3268 
3269   FileLen = strlen (StringFileName) + 1;
3270   mStringFileName = new CHAR8[FileLen];
3271   if (mStringFileName == NULL) {
3272     return;
3273   }
3274 
3275   strcpy (mStringFileName, StringFileName);
3276   mStringFileName[FileLen - 1] = '\0';
3277 }
3278 
3279 
3280 /**
3281   Returns TRUE or FALSE whether SupportedLanguages contains the best matching language
3282   from a set of supported languages.
3283 
3284   @param[in]  SupportedLanguages  A pointer to a Null-terminated ASCII string that
3285                                   contains a set of language codes.
3286   @param[in]  Language            A variable that contains pointers to Null-terminated
3287                                   ASCII strings that contain one language codes.
3288 
3289   @retval FALSE   The best matching language could not be found in SupportedLanguages.
3290   @retval TRUE    The best matching language could be found in SupportedLanguages.
3291 
3292 **/
3293 BOOLEAN
GetBestLanguage(IN CONST CHAR8 * SupportedLanguages,IN CHAR8 * Language)3294 CVfrStringDB::GetBestLanguage (
3295   IN CONST CHAR8  *SupportedLanguages,
3296   IN CHAR8        *Language
3297   )
3298 {
3299   UINTN        CompareLength;
3300   UINTN        LanguageLength;
3301   CONST CHAR8  *Supported;
3302 
3303   if (SupportedLanguages == NULL || Language == NULL){
3304     return FALSE;
3305   }
3306 
3307   //
3308   // Determine the length of the first RFC 4646 language code in Language
3309   //
3310   for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
3311 
3312   //
3313   // Trim back the length of Language used until it is empty
3314   //
3315   while (LanguageLength > 0) {
3316     //
3317     // Loop through all language codes in SupportedLanguages
3318     //
3319     for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
3320       //
3321       // Skip ';' characters in Supported
3322       //
3323       for (; *Supported != '\0' && *Supported == ';'; Supported++);
3324       //
3325       // Determine the length of the next language code in Supported
3326       //
3327       for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
3328       //
3329       // If Language is longer than the Supported, then skip to the next language
3330       //
3331       if (LanguageLength > CompareLength) {
3332         continue;
3333       }
3334 
3335       //
3336       // See if the first LanguageLength characters in Supported match Language
3337       //
3338       if (strncmp (Supported, Language, LanguageLength) == 0) {
3339         return TRUE;
3340       }
3341     }
3342 
3343     //
3344     // Trim Language from the right to the next '-' character
3345     //
3346     for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
3347   }
3348 
3349   //
3350   // No matches were found
3351   //
3352   return FALSE;
3353 }
3354 
3355 
3356 CHAR8 *
GetVarStoreNameFormStringId(IN EFI_STRING_ID StringId)3357 CVfrStringDB::GetVarStoreNameFormStringId (
3358   IN EFI_STRING_ID StringId
3359   )
3360 {
3361   FILE        *pInFile    = NULL;
3362   UINT32      NameOffset;
3363   UINT32      Length;
3364   UINT8       *StringPtr;
3365   CHAR8       *StringName;
3366   CHAR16      *UnicodeString;
3367   CHAR8       *VarStoreName = NULL;
3368   CHAR8       *DestTmp;
3369   UINT8       *Current;
3370   EFI_STATUS  Status;
3371   CHAR8       LineBuf[EFI_IFR_MAX_LENGTH];
3372   UINT8       BlockType;
3373   EFI_HII_STRING_PACKAGE_HDR *PkgHeader;
3374 
3375   if (mStringFileName == NULL) {
3376     return NULL;
3377   }
3378 
3379   if ((pInFile = fopen (LongFilePath (mStringFileName), "rb")) == NULL) {
3380     return NULL;
3381   }
3382 
3383   //
3384   // Get file length.
3385   //
3386   fseek (pInFile, 0, SEEK_END);
3387   Length = ftell (pInFile);
3388   fseek (pInFile, 0, SEEK_SET);
3389 
3390   //
3391   // Get file data.
3392   //
3393   StringPtr = new UINT8[Length];
3394   if (StringPtr == NULL) {
3395     fclose (pInFile);
3396     return NULL;
3397   }
3398   fread ((char *)StringPtr, sizeof (UINT8), Length, pInFile);
3399   fclose (pInFile);
3400 
3401   PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
3402   //
3403   // Check the String package.
3404   //
3405   if (PkgHeader->Header.Type != EFI_HII_PACKAGE_STRINGS) {
3406     delete[] StringPtr;
3407     return NULL;
3408   }
3409 
3410   //
3411   // Search the language, get best language base on RFC 4647 matching algorithm.
3412   //
3413   Current = StringPtr;
3414   while (!GetBestLanguage ("en", PkgHeader->Language)) {
3415     Current += PkgHeader->Header.Length;
3416     PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current;
3417     //
3418     // If can't find string package base on language, just return the first string package.
3419     //
3420     if (Current - StringPtr >= Length) {
3421       Current = StringPtr;
3422       PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr;
3423       break;
3424     }
3425   }
3426 
3427   Current += PkgHeader->HdrSize;
3428   //
3429   // Find the string block according the stringId.
3430   //
3431   Status = FindStringBlock(Current, StringId, &NameOffset, &BlockType);
3432   if (Status != EFI_SUCCESS) {
3433     delete[] StringPtr;
3434     return NULL;
3435   }
3436 
3437   //
3438   // Get varstore name according the string type.
3439   //
3440   switch (BlockType) {
3441   case EFI_HII_SIBT_STRING_SCSU:
3442   case EFI_HII_SIBT_STRING_SCSU_FONT:
3443   case EFI_HII_SIBT_STRINGS_SCSU:
3444   case EFI_HII_SIBT_STRINGS_SCSU_FONT:
3445     StringName = (CHAR8*)(Current + NameOffset);
3446     VarStoreName = new CHAR8[strlen(StringName) + 1];
3447     strcpy (VarStoreName, StringName);
3448     break;
3449   case EFI_HII_SIBT_STRING_UCS2:
3450   case EFI_HII_SIBT_STRING_UCS2_FONT:
3451   case EFI_HII_SIBT_STRINGS_UCS2:
3452   case EFI_HII_SIBT_STRINGS_UCS2_FONT:
3453     UnicodeString = (CHAR16*)(Current + NameOffset);
3454     Length = GetUnicodeStringTextSize ((UINT8*)UnicodeString) ;
3455     DestTmp = new CHAR8[Length / 2 + 1];
3456     VarStoreName = DestTmp;
3457     while (*UnicodeString != '\0') {
3458       *(DestTmp++) = (CHAR8) *(UnicodeString++);
3459     }
3460     *DestTmp = '\0';
3461     break;
3462   default:
3463     break;
3464   }
3465 
3466   delete[] StringPtr;
3467 
3468   return VarStoreName;
3469 }
3470 
3471 EFI_STATUS
FindStringBlock(IN UINT8 * StringData,IN EFI_STRING_ID StringId,OUT UINT32 * StringTextOffset,OUT UINT8 * BlockType)3472 CVfrStringDB::FindStringBlock (
3473   IN  UINT8                           *StringData,
3474   IN  EFI_STRING_ID                   StringId,
3475   OUT UINT32                          *StringTextOffset,
3476   OUT UINT8                           *BlockType
3477   )
3478 {
3479   UINT8                                *BlockHdr;
3480   EFI_STRING_ID                        CurrentStringId;
3481   UINT32                               BlockSize;
3482   UINT32                               Index;
3483   UINT8                                *StringTextPtr;
3484   UINT32                               Offset;
3485   UINT16                               StringCount;
3486   UINT16                               SkipCount;
3487   UINT8                                Length8;
3488   EFI_HII_SIBT_EXT2_BLOCK              Ext2;
3489   UINT32                               Length32;
3490   UINT32                               StringSize;
3491 
3492   CurrentStringId = 1;
3493 
3494   //
3495   // Parse the string blocks to get the string text and font.
3496   //
3497   BlockHdr  = StringData;
3498   BlockSize = 0;
3499   Offset    = 0;
3500   while (*BlockHdr != EFI_HII_SIBT_END) {
3501     switch (*BlockHdr) {
3502     case EFI_HII_SIBT_STRING_SCSU:
3503       Offset = sizeof (EFI_HII_STRING_BLOCK);
3504       StringTextPtr = BlockHdr + Offset;
3505       BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
3506       CurrentStringId++;
3507       break;
3508 
3509     case EFI_HII_SIBT_STRING_SCSU_FONT:
3510       Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
3511       StringTextPtr = BlockHdr + Offset;
3512       BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1;
3513       CurrentStringId++;
3514       break;
3515 
3516     case EFI_HII_SIBT_STRINGS_SCSU:
3517       memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
3518       StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);
3519       BlockSize += StringTextPtr - BlockHdr;
3520 
3521       for (Index = 0; Index < StringCount; Index++) {
3522         BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
3523         if (CurrentStringId == StringId) {
3524           *BlockType        = *BlockHdr;
3525           *StringTextOffset = StringTextPtr - StringData;
3526           return EFI_SUCCESS;
3527         }
3528         StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
3529         CurrentStringId++;
3530       }
3531       break;
3532 
3533     case EFI_HII_SIBT_STRINGS_SCSU_FONT:
3534       memcpy (
3535         &StringCount,
3536         BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3537         sizeof (UINT16)
3538         );
3539       StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);
3540       BlockSize += StringTextPtr - BlockHdr;
3541 
3542       for (Index = 0; Index < StringCount; Index++) {
3543         BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1;
3544         if (CurrentStringId == StringId) {
3545           *BlockType        = *BlockHdr;
3546           *StringTextOffset = StringTextPtr - StringData;
3547           return EFI_SUCCESS;
3548         }
3549         StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1;
3550         CurrentStringId++;
3551       }
3552       break;
3553 
3554     case EFI_HII_SIBT_STRING_UCS2:
3555       Offset        = sizeof (EFI_HII_STRING_BLOCK);
3556       StringTextPtr = BlockHdr + Offset;
3557       //
3558       // Use StringSize to store the size of the specified string, including the NULL
3559       // terminator.
3560       //
3561       StringSize = GetUnicodeStringTextSize (StringTextPtr);
3562       BlockSize += Offset + StringSize;
3563       CurrentStringId++;
3564       break;
3565 
3566     case EFI_HII_SIBT_STRING_UCS2_FONT:
3567       Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK)  - sizeof (CHAR16);
3568       StringTextPtr = BlockHdr + Offset;
3569       //
3570       // Use StrSize to store the size of the specified string, including the NULL
3571       // terminator.
3572       //
3573       StringSize = GetUnicodeStringTextSize (StringTextPtr);
3574       BlockSize += Offset + StringSize;
3575       CurrentStringId++;
3576       break;
3577 
3578     case EFI_HII_SIBT_STRINGS_UCS2:
3579       Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
3580       StringTextPtr = BlockHdr + Offset;
3581       BlockSize += Offset;
3582       memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
3583       for (Index = 0; Index < StringCount; Index++) {
3584         StringSize = GetUnicodeStringTextSize (StringTextPtr);
3585         BlockSize += StringSize;
3586         if (CurrentStringId == StringId) {
3587           *BlockType        = *BlockHdr;
3588           *StringTextOffset = StringTextPtr - StringData;
3589           return EFI_SUCCESS;
3590         }
3591         StringTextPtr = StringTextPtr + StringSize;
3592         CurrentStringId++;
3593       }
3594       break;
3595 
3596     case EFI_HII_SIBT_STRINGS_UCS2_FONT:
3597       Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
3598       StringTextPtr = BlockHdr + Offset;
3599       BlockSize += Offset;
3600       memcpy (
3601         &StringCount,
3602         BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3603         sizeof (UINT16)
3604         );
3605       for (Index = 0; Index < StringCount; Index++) {
3606         StringSize = GetUnicodeStringTextSize (StringTextPtr);
3607         BlockSize += StringSize;
3608         if (CurrentStringId == StringId) {
3609           *BlockType        = *BlockHdr;
3610           *StringTextOffset = StringTextPtr - StringData;
3611           return EFI_SUCCESS;
3612         }
3613         StringTextPtr = StringTextPtr + StringSize;
3614         CurrentStringId++;
3615       }
3616       break;
3617 
3618     case EFI_HII_SIBT_DUPLICATE:
3619       if (CurrentStringId == StringId) {
3620         //
3621         // Incoming StringId is an id of a duplicate string block.
3622         // Update the StringId to be the previous string block.
3623         // Go back to the header of string block to search.
3624         //
3625         memcpy (
3626           &StringId,
3627           BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
3628           sizeof (EFI_STRING_ID)
3629           );
3630         CurrentStringId = 1;
3631         BlockSize       = 0;
3632       } else {
3633         BlockSize       += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
3634         CurrentStringId++;
3635       }
3636       break;
3637 
3638     case EFI_HII_SIBT_SKIP1:
3639       SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
3640       CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
3641       BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
3642       break;
3643 
3644     case EFI_HII_SIBT_SKIP2:
3645       memcpy (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
3646       CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
3647       BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
3648       break;
3649 
3650     case EFI_HII_SIBT_EXT1:
3651       memcpy (
3652         &Length8,
3653         BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3654         sizeof (UINT8)
3655         );
3656       BlockSize += Length8;
3657       break;
3658 
3659     case EFI_HII_SIBT_EXT2:
3660       memcpy (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
3661       BlockSize += Ext2.Length;
3662       break;
3663 
3664     case EFI_HII_SIBT_EXT4:
3665       memcpy (
3666         &Length32,
3667         BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
3668         sizeof (UINT32)
3669         );
3670 
3671       BlockSize += Length32;
3672       break;
3673 
3674     default:
3675       break;
3676     }
3677 
3678     if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) {
3679       *StringTextOffset = BlockHdr - StringData + Offset;
3680       *BlockType        = *BlockHdr;
3681 
3682       if (StringId == CurrentStringId - 1) {
3683         //
3684         // if only one skip item, return EFI_NOT_FOUND.
3685         //
3686         if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) {
3687           return EFI_NOT_FOUND;
3688         } else {
3689           return EFI_SUCCESS;
3690         }
3691       }
3692 
3693       if (StringId < CurrentStringId - 1) {
3694         return EFI_NOT_FOUND;
3695       }
3696     }
3697     BlockHdr  = StringData + BlockSize;
3698   }
3699 
3700   return EFI_NOT_FOUND;
3701 }
3702 
3703 UINT32
GetUnicodeStringTextSize(IN UINT8 * StringSrc)3704 CVfrStringDB::GetUnicodeStringTextSize (
3705   IN  UINT8            *StringSrc
3706   )
3707 {
3708   UINT32 StringSize;
3709   CHAR16 *StringPtr;
3710 
3711   StringSize = sizeof (CHAR16);
3712   StringPtr  = (UINT16*)StringSrc;
3713   while (*StringPtr++ != L'\0') {
3714     StringSize += sizeof (CHAR16);
3715   }
3716 
3717   return StringSize;
3718 }
3719 
3720 BOOLEAN  VfrCompatibleMode = FALSE;
3721 
3722 CVfrVarDataTypeDB gCVfrVarDataTypeDB;
3723 CVfrDefaultStore  gCVfrDefaultStore;
3724 CVfrDataStorage  gCVfrDataStorage;
3725 
3726 
3727