]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp
Sync BaseTools Trunk (version r2518) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / VfrCompile / VfrFormPkg.cpp
1 /** @file
2
3 The definition of CFormPkg's member function
4
5 Copyright (c) 2004 - 2012, 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 "VfrFormPkg.h"
18
19 /*
20 * The definition of CFormPkg's member function
21 */
22
23 SPendingAssign::SPendingAssign (
24 IN CHAR8 *Key,
25 IN VOID *Addr,
26 IN UINT32 Len,
27 IN UINT32 LineNo,
28 IN CONST CHAR8 *Msg
29 )
30 {
31 mKey = NULL;
32 mAddr = Addr;
33 mLen = Len;
34 mFlag = PENDING;
35 mLineNo = LineNo;
36 mMsg = NULL;
37 mNext = NULL;
38 if (Key != NULL) {
39 mKey = new CHAR8[strlen (Key) + 1];
40 if (mKey != NULL) {
41 strcpy (mKey, Key);
42 }
43 }
44
45 if (Msg != NULL) {
46 mMsg = new CHAR8[strlen (Msg) + 1];
47 if (mMsg != NULL) {
48 strcpy (mMsg, Msg);
49 }
50 }
51 }
52
53 SPendingAssign::~SPendingAssign (
54 VOID
55 )
56 {
57 if (mKey != NULL) {
58 delete mKey;
59 }
60 mAddr = NULL;
61 mLen = 0;
62 mLineNo = 0;
63 if (mMsg != NULL) {
64 delete mMsg;
65 }
66 mNext = NULL;
67 }
68
69 VOID
70 SPendingAssign::SetAddrAndLen (
71 IN VOID *Addr,
72 IN UINT32 LineNo
73 )
74 {
75 mAddr = Addr;
76 mLineNo = LineNo;
77 }
78
79 VOID
80 SPendingAssign::AssignValue (
81 IN VOID *Addr,
82 IN UINT32 Len
83 )
84 {
85 memcpy (mAddr, Addr, (mLen < Len ? mLen : Len));
86 mFlag = ASSIGNED;
87 }
88
89 CHAR8 *
90 SPendingAssign::GetKey (
91 VOID
92 )
93 {
94 return mKey;
95 }
96
97 CFormPkg::CFormPkg (
98 IN UINT32 BufferSize = 4096
99 )
100 {
101 CHAR8 *BufferStart;
102 CHAR8 *BufferEnd;
103 SBufferNode *Node;
104
105 mPkgLength = 0;
106 mBufferNodeQueueHead = NULL;
107 mCurrBufferNode = NULL;
108
109 Node = new SBufferNode;
110 if (Node == NULL) {
111 return ;
112 }
113 BufferStart = new CHAR8[BufferSize];
114 if (BufferStart == NULL) {
115 return;
116 }
117 BufferEnd = BufferStart + BufferSize;
118
119 memset (BufferStart, 0, BufferSize);
120 Node->mBufferStart = BufferStart;
121 Node->mBufferEnd = BufferEnd;
122 Node->mBufferFree = BufferStart;
123 Node->mNext = NULL;
124
125 mBufferSize = BufferSize;
126 mBufferNodeQueueHead = Node;
127 mBufferNodeQueueTail = Node;
128 mCurrBufferNode = Node;
129 }
130
131 CFormPkg::~CFormPkg ()
132 {
133 SBufferNode *pBNode;
134 SPendingAssign *pPNode;
135
136 while (mBufferNodeQueueHead != NULL) {
137 pBNode = mBufferNodeQueueHead;
138 mBufferNodeQueueHead = mBufferNodeQueueHead->mNext;
139 if (pBNode->mBufferStart != NULL) {
140 delete pBNode->mBufferStart;
141 delete pBNode;
142 }
143 }
144 mBufferNodeQueueTail = NULL;
145 mCurrBufferNode = NULL;
146
147 while (PendingAssignList != NULL) {
148 pPNode = PendingAssignList;
149 PendingAssignList = PendingAssignList->mNext;
150 delete pPNode;
151 }
152 PendingAssignList = NULL;
153 }
154
155 CHAR8 *
156 CFormPkg::IfrBinBufferGet (
157 IN UINT32 Len
158 )
159 {
160 CHAR8 *BinBuffer = NULL;
161
162 if ((Len == 0) || (Len > mBufferSize)) {
163 return NULL;
164 }
165
166 if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) {
167 BinBuffer = mCurrBufferNode->mBufferFree;
168 mCurrBufferNode->mBufferFree += Len;
169 } else {
170 SBufferNode *Node;
171
172 Node = new SBufferNode;
173 if (Node == NULL) {
174 return NULL;
175 }
176
177 Node->mBufferStart = new CHAR8[mBufferSize];
178 if (Node->mBufferStart == NULL) {
179 delete Node;
180 return NULL;
181 } else {
182 memset (Node->mBufferStart, 0, mBufferSize);
183 Node->mBufferEnd = Node->mBufferStart + mBufferSize;
184 Node->mBufferFree = Node->mBufferStart;
185 Node->mNext = NULL;
186 }
187
188 if (mBufferNodeQueueTail == NULL) {
189 mBufferNodeQueueHead = mBufferNodeQueueTail = Node;
190 } else {
191 mBufferNodeQueueTail->mNext = Node;
192 mBufferNodeQueueTail = Node;
193 }
194 mCurrBufferNode = Node;
195
196 //
197 // Now try again.
198 //
199 BinBuffer = mCurrBufferNode->mBufferFree;
200 mCurrBufferNode->mBufferFree += Len;
201 }
202
203 mPkgLength += Len;
204
205 return BinBuffer;
206 }
207
208 inline
209 UINT32
210 CFormPkg::GetPkgLength (
211 VOID
212 )
213 {
214 return mPkgLength;
215 }
216
217 VOID
218 CFormPkg::Open (
219 VOID
220 )
221 {
222 mReadBufferNode = mBufferNodeQueueHead;
223 mReadBufferOffset = 0;
224 }
225
226 VOID
227 CFormPkg::Close (
228 VOID
229 )
230 {
231 mReadBufferNode = NULL;
232 mReadBufferOffset = 0;
233 }
234
235 UINT32
236 CFormPkg::Read (
237 IN CHAR8 *Buffer,
238 IN UINT32 Size
239 )
240 {
241 UINT32 Index;
242
243 if ((Size == 0) || (Buffer == NULL)) {
244 return 0;
245 }
246
247 if (mReadBufferNode == NULL) {
248 return 0;
249 }
250
251 for (Index = 0; Index < Size; Index++) {
252 if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) {
253 Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++];
254 } else {
255 if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) {
256 return Index;
257 } else {
258 mReadBufferOffset = 0;
259 Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++];
260 }
261 }
262 }
263
264 return Size;
265 }
266
267 EFI_VFR_RETURN_CODE
268 CFormPkg::BuildPkgHdr (
269 OUT EFI_HII_PACKAGE_HEADER **PkgHdr
270 )
271 {
272 if (PkgHdr == NULL) {
273 return VFR_RETURN_FATAL_ERROR;
274 }
275
276 if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) {
277 return VFR_RETURN_OUT_FOR_RESOURCES;
278 }
279
280 (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM;
281 (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER);
282
283 return VFR_RETURN_SUCCESS;
284 }
285
286 EFI_VFR_RETURN_CODE
287 CFormPkg::BuildPkg (
288 OUT PACKAGE_DATA &TBuffer
289 )
290 {
291
292 CHAR8 *Temp;
293 UINT32 Size;
294 CHAR8 Buffer[1024];
295
296 if (TBuffer.Buffer != NULL) {
297 delete TBuffer.Buffer;
298 }
299
300 TBuffer.Size = mPkgLength;
301 TBuffer.Buffer = NULL;
302 if (TBuffer.Size != 0) {
303 TBuffer.Buffer = new CHAR8[TBuffer.Size];
304 } else {
305 return VFR_RETURN_SUCCESS;
306 }
307
308 Temp = TBuffer.Buffer;
309 Open ();
310 while ((Size = Read (Buffer, 1024)) != 0) {
311 memcpy (Temp, Buffer, Size);
312 Temp += Size;
313 }
314 Close ();
315 return VFR_RETURN_SUCCESS;
316 }
317
318
319 EFI_VFR_RETURN_CODE
320 CFormPkg::BuildPkg (
321 IN FILE *Output,
322 IN PACKAGE_DATA *PkgData
323 )
324 {
325 EFI_VFR_RETURN_CODE Ret;
326 CHAR8 Buffer[1024];
327 UINT32 Size;
328 EFI_HII_PACKAGE_HEADER *PkgHdr;
329
330 if (Output == NULL) {
331 return VFR_RETURN_FATAL_ERROR;
332 }
333
334 if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
335 return Ret;
336 }
337 fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output);
338 delete PkgHdr;
339
340 if (PkgData == NULL) {
341 Open ();
342 while ((Size = Read (Buffer, 1024)) != 0) {
343 fwrite (Buffer, Size, 1, Output);
344 }
345 Close ();
346 } else {
347 fwrite (PkgData->Buffer, PkgData->Size, 1, Output);
348 }
349
350 return VFR_RETURN_SUCCESS;
351 }
352
353 VOID
354 CFormPkg::_WRITE_PKG_LINE (
355 IN FILE *pFile,
356 IN UINT32 LineBytes,
357 IN CONST CHAR8 *LineHeader,
358 IN CHAR8 *BlkBuf,
359 IN UINT32 BlkSize
360 )
361 {
362 UINT32 Index;
363
364 if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
365 return;
366 }
367
368 for (Index = 0; Index < BlkSize; Index++) {
369 if ((Index % LineBytes) == 0) {
370 fprintf (pFile, "\n%s", LineHeader);
371 }
372 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);
373 }
374 }
375
376 VOID
377 CFormPkg::_WRITE_PKG_END (
378 IN FILE *pFile,
379 IN UINT32 LineBytes,
380 IN CONST CHAR8 *LineHeader,
381 IN CHAR8 *BlkBuf,
382 IN UINT32 BlkSize
383 )
384 {
385 UINT32 Index;
386
387 if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {
388 return;
389 }
390
391 for (Index = 0; Index < BlkSize - 1; Index++) {
392 if ((Index % LineBytes) == 0) {
393 fprintf (pFile, "\n%s", LineHeader);
394 }
395 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);
396 }
397
398 if ((Index % LineBytes) == 0) {
399 fprintf (pFile, "\n%s", LineHeader);
400 }
401 fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);
402 }
403
404 #define BYTES_PRE_LINE 0x10
405
406 EFI_VFR_RETURN_CODE
407 CFormPkg::GenCFile (
408 IN CHAR8 *BaseName,
409 IN FILE *pFile,
410 IN PACKAGE_DATA *PkgData
411 )
412 {
413 EFI_VFR_RETURN_CODE Ret;
414 CHAR8 Buffer[BYTES_PRE_LINE * 8];
415 EFI_HII_PACKAGE_HEADER *PkgHdr;
416 UINT32 PkgLength = 0;
417 UINT32 ReadSize = 0;
418
419 if ((BaseName == NULL) || (pFile == NULL)) {
420 return VFR_RETURN_FATAL_ERROR;
421 }
422
423 fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName);
424
425 if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {
426 return Ret;
427 }
428
429 //
430 // For framework vfr file, the extension framework header will be added.
431 //
432 if (VfrCompatibleMode) {
433 fprintf (pFile, " // FRAMEWORK PACKAGE HEADER Length\n");
434 PkgLength = PkgHdr->Length + sizeof (UINT32) + 2;
435 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32));
436 fprintf (pFile, "\n\n // FRAMEWORK PACKAGE HEADER Type\n");
437 PkgLength = 3;
438 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT16));
439 } else {
440 fprintf (pFile, " // ARRAY LENGTH\n");
441 PkgLength = PkgHdr->Length + sizeof (UINT32);
442 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32));
443 }
444
445 fprintf (pFile, "\n\n // PACKAGE HEADER\n");
446 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER));
447 PkgLength = sizeof (EFI_HII_PACKAGE_HEADER);
448
449 fprintf (pFile, "\n\n // PACKAGE DATA\n");
450
451 if (PkgData == NULL) {
452 Open ();
453 while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) {
454 PkgLength += ReadSize;
455 if (PkgLength < PkgHdr->Length) {
456 _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize);
457 } else {
458 _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize);
459 }
460 }
461 Close ();
462 } else {
463 if (PkgData->Size % BYTES_PRE_LINE != 0) {
464 PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE);
465 _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength);
466 _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE);
467 } else {
468 PkgLength = PkgData->Size - BYTES_PRE_LINE;
469 _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength);
470 _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE);
471 }
472 }
473
474 delete PkgHdr;
475 fprintf (pFile, "\n};\n");
476
477 return VFR_RETURN_SUCCESS;
478 }
479
480 EFI_VFR_RETURN_CODE
481 CFormPkg::AssignPending (
482 IN CHAR8 *Key,
483 IN VOID *ValAddr,
484 IN UINT32 ValLen,
485 IN UINT32 LineNo,
486 IN CONST CHAR8 *Msg
487 )
488 {
489 SPendingAssign *pNew;
490
491 pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg);
492 if (pNew == NULL) {
493 return VFR_RETURN_OUT_FOR_RESOURCES;
494 }
495
496 pNew->mNext = PendingAssignList;
497 PendingAssignList = pNew;
498 return VFR_RETURN_SUCCESS;
499 }
500
501 VOID
502 CFormPkg::DoPendingAssign (
503 IN CHAR8 *Key,
504 IN VOID *ValAddr,
505 IN UINT32 ValLen
506 )
507 {
508 SPendingAssign *pNode;
509
510 if ((Key == NULL) || (ValAddr == NULL)) {
511 return;
512 }
513
514 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
515 if (strcmp (pNode->mKey, Key) == 0) {
516 pNode->AssignValue (ValAddr, ValLen);
517 }
518 }
519 }
520
521 bool
522 CFormPkg::HavePendingUnassigned (
523 VOID
524 )
525 {
526 SPendingAssign *pNode;
527
528 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
529 if (pNode->mFlag == PENDING) {
530 return TRUE;
531 }
532 }
533
534 return FALSE;
535 }
536
537 VOID
538 CFormPkg::PendingAssignPrintAll (
539 VOID
540 )
541 {
542 SPendingAssign *pNode;
543
544 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
545 if (pNode->mFlag == PENDING) {
546 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg);
547 }
548 }
549 }
550
551 EFI_VFR_RETURN_CODE
552 CFormPkg::DeclarePendingQuestion (
553 IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB,
554 IN CVfrDataStorage &lCVfrDataStorage,
555 IN CVfrQuestionDB &lCVfrQuestionDB,
556 IN EFI_GUID *LocalFormSetGuid,
557 IN UINT32 LineNo
558 )
559 {
560 SPendingAssign *pNode;
561 CHAR8 *VarStr;
562 UINT32 ArrayIdx;
563 CHAR8 FName[MAX_NAME_LEN];
564 CHAR8 *SName;
565 CHAR8 *NewStr;
566 EFI_VFR_RETURN_CODE ReturnCode;
567 EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID;
568
569 //
570 // Declare all questions as Numeric in DisableIf True
571 //
572 // DisableIf
573 CIfrDisableIf DIObj;
574 DIObj.SetLineNo (LineNo);
575
576 //TrueOpcode
577 CIfrTrue TObj (LineNo);
578
579 // Declare Numeric qeustion for each undefined question.
580 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {
581 if (pNode->mFlag == PENDING) {
582 CIfrNumeric CNObj;
583 EFI_VARSTORE_INFO Info;
584 EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID;
585
586 CNObj.SetLineNo (LineNo);
587 CNObj.SetPrompt (0x0);
588 CNObj.SetHelp (0x0);
589
590 //
591 // Register this question, assume it is normal question, not date or time question
592 //
593 VarStr = pNode->mKey;
594 ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId);
595 if (ReturnCode != VFR_RETURN_SUCCESS) {
596 gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
597 return ReturnCode;
598 }
599
600 #ifdef VFREXP_DEBUG
601 printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId);
602 #endif
603 //
604 // Get Question Info, framework vfr VarName == StructName
605 //
606 ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx);
607 if (ReturnCode != VFR_RETURN_SUCCESS) {
608 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable");
609 return ReturnCode;
610 }
611 //
612 // Get VarStoreType
613 //
614 ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType);
615 if (ReturnCode == VFR_RETURN_UNDEFINED) {
616 lCVfrDataStorage.DeclareBufferVarStore (
617 FName,
618 LocalFormSetGuid,
619 &lCVfrVarDataTypeDB,
620 FName,
621 EFI_VARSTORE_ID_INVALID,
622 FALSE
623 );
624 ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType);
625 }
626 if (ReturnCode != VFR_RETURN_SUCCESS) {
627 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined");
628 return ReturnCode;
629 }
630
631 ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId);
632 if (ReturnCode != VFR_RETURN_SUCCESS) {
633 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined");
634 return ReturnCode;
635 }
636
637 if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) {
638 ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx);
639 } else {
640 if (VarStoreType == EFI_VFR_VARSTORE_EFI) {
641 ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info);
642 } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER) {
643 VarStr = pNode->mKey;
644 //convert VarStr with store name to VarStr with structure name
645 ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (FName, &SName);
646 if (ReturnCode == VFR_RETURN_SUCCESS) {
647 NewStr = new CHAR8[strlen (VarStr) + strlen (SName) + 1];
648 NewStr[0] = '\0';
649 strcpy (NewStr, SName);
650 strcat (NewStr, VarStr + strlen (FName));
651 ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize);
652 delete NewStr;
653 }
654 } else {
655 ReturnCode = VFR_RETURN_UNSUPPORTED;
656 }
657 }
658 if (ReturnCode != VFR_RETURN_SUCCESS) {
659 gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);
660 return ReturnCode;
661 }
662
663 CNObj.SetQuestionId (QId);
664 CNObj.SetVarStoreInfo (&Info);
665 //
666 // Numeric doesn't support BOOLEAN data type.
667 // BOOLEAN type has the same data size to UINT8.
668 //
669 if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) {
670 Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8;
671 }
672 CNObj.SetFlags (0, Info.mVarType);
673 //
674 // Use maximum value not to limit the vaild value for the undefined question.
675 //
676 switch (Info.mVarType) {
677 case EFI_IFR_TYPE_NUM_SIZE_64:
678 CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0);
679 break;
680 case EFI_IFR_TYPE_NUM_SIZE_32:
681 CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0);
682 break;
683 case EFI_IFR_TYPE_NUM_SIZE_16:
684 CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0);
685 break;
686 case EFI_IFR_TYPE_NUM_SIZE_8:
687 CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0);
688 break;
689 default:
690 break;
691 }
692
693 //
694 // For undefined Efi VarStore type question
695 // Append the extended guided opcode to contain VarName
696 //
697 if (VarStoreType == EFI_VFR_VARSTORE_EFI || VfrCompatibleMode) {
698 CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName);
699 CVNObj.SetLineNo (LineNo);
700 }
701
702 //
703 // End for Numeric
704 //
705 CIfrEnd CEObj;
706 CEObj.SetLineNo (LineNo);
707 }
708 }
709
710 //
711 // End for DisableIf
712 //
713 CIfrEnd SEObj;
714 SEObj.SetLineNo (LineNo);
715
716 return VFR_RETURN_SUCCESS;
717 }
718
719 CFormPkg gCFormPkg;
720
721 SIfrRecord::SIfrRecord (
722 VOID
723 )
724 {
725 mIfrBinBuf = NULL;
726 mBinBufLen = 0;
727 mLineNo = 0xFFFFFFFF;
728 mOffset = 0xFFFFFFFF;
729 mNext = NULL;
730 }
731
732 SIfrRecord::~SIfrRecord (
733 VOID
734 )
735 {
736 if (mIfrBinBuf != NULL) {
737 //delete mIfrBinBuf;
738 mIfrBinBuf = NULL;
739 }
740 mLineNo = 0xFFFFFFFF;
741 mOffset = 0xFFFFFFFF;
742 mBinBufLen = 0;
743 mNext = NULL;
744 }
745
746 CIfrRecordInfoDB::CIfrRecordInfoDB (
747 VOID
748 )
749 {
750 mSwitch = TRUE;
751 mRecordCount = EFI_IFR_RECORDINFO_IDX_START;
752 mIfrRecordListHead = NULL;
753 mIfrRecordListTail = NULL;
754 }
755
756 CIfrRecordInfoDB::~CIfrRecordInfoDB (
757 VOID
758 )
759 {
760 SIfrRecord *pNode;
761
762 while (mIfrRecordListHead != NULL) {
763 pNode = mIfrRecordListHead;
764 mIfrRecordListHead = mIfrRecordListHead->mNext;
765 delete pNode;
766 }
767 }
768
769 SIfrRecord *
770 CIfrRecordInfoDB::GetRecordInfoFromIdx (
771 IN UINT32 RecordIdx
772 )
773 {
774 UINT32 Idx;
775 SIfrRecord *pNode = NULL;
776
777 if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) {
778 return NULL;
779 }
780
781 for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead;
782 (Idx != RecordIdx) && (pNode != NULL);
783 Idx++, pNode = pNode->mNext)
784 ;
785
786 return pNode;
787 }
788
789 UINT32
790 CIfrRecordInfoDB::IfrRecordRegister (
791 IN UINT32 LineNo,
792 IN CHAR8 *IfrBinBuf,
793 IN UINT8 BinBufLen,
794 IN UINT32 Offset
795 )
796 {
797 SIfrRecord *pNew;
798
799 if (mSwitch == FALSE) {
800 return EFI_IFR_RECORDINFO_IDX_INVALUD;
801 }
802
803 if ((pNew = new SIfrRecord) == NULL) {
804 return EFI_IFR_RECORDINFO_IDX_INVALUD;
805 }
806
807 if (mIfrRecordListHead == NULL) {
808 mIfrRecordListHead = pNew;
809 mIfrRecordListTail = pNew;
810 } else {
811 mIfrRecordListTail->mNext = pNew;
812 mIfrRecordListTail = pNew;
813 }
814 mRecordCount++;
815
816 return mRecordCount;
817 }
818
819 VOID
820 CIfrRecordInfoDB::IfrRecordInfoUpdate (
821 IN UINT32 RecordIdx,
822 IN UINT32 LineNo,
823 IN CHAR8 *BinBuf,
824 IN UINT8 BinBufLen,
825 IN UINT32 Offset
826 )
827 {
828 SIfrRecord *pNode;
829 SIfrRecord *Prev;
830
831 if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) {
832 return;
833 }
834
835 if (LineNo == 0) {
836 //
837 // Line number is not specified explicitly, try to use line number of previous opcode
838 //
839 Prev = GetRecordInfoFromIdx (RecordIdx - 1);
840 if (Prev != NULL) {
841 LineNo = Prev->mLineNo;
842 }
843 }
844
845 pNode->mLineNo = LineNo;
846 pNode->mOffset = Offset;
847 pNode->mBinBufLen = BinBufLen;
848 pNode->mIfrBinBuf = BinBuf;
849
850 }
851
852 VOID
853 CIfrRecordInfoDB::IfrRecordOutput (
854 OUT PACKAGE_DATA &TBuffer
855 )
856 {
857 CHAR8 *Temp;
858 SIfrRecord *pNode;
859
860 if (TBuffer.Buffer != NULL) {
861 delete TBuffer.Buffer;
862 }
863
864 TBuffer.Size = 0;
865 TBuffer.Buffer = NULL;
866
867
868 if (mSwitch == FALSE) {
869 return;
870 }
871
872 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
873 TBuffer.Size += pNode->mBinBufLen;
874 }
875
876 if (TBuffer.Size != 0) {
877 TBuffer.Buffer = new CHAR8[TBuffer.Size];
878 } else {
879 return;
880 }
881
882 Temp = TBuffer.Buffer;
883
884 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
885 if (pNode->mIfrBinBuf != NULL) {
886 memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen);
887 Temp += pNode->mBinBufLen;
888 }
889 }
890
891 return;
892 }
893
894 VOID
895 CIfrRecordInfoDB::IfrRecordOutput (
896 IN FILE *File,
897 IN UINT32 LineNo
898 )
899 {
900 SIfrRecord *pNode;
901 UINT8 Index;
902 UINT32 TotalSize;
903
904 if (mSwitch == FALSE) {
905 return;
906 }
907
908 if (File == NULL) {
909 return;
910 }
911
912 TotalSize = 0;
913
914 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
915 if (pNode->mLineNo == LineNo || LineNo == 0) {
916 fprintf (File, ">%08X: ", pNode->mOffset);
917 TotalSize += pNode->mBinBufLen;
918 if (pNode->mIfrBinBuf != NULL) {
919 for (Index = 0; Index < pNode->mBinBufLen; Index++) {
920 fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index]));
921 }
922 }
923 fprintf (File, "\n");
924 }
925 }
926
927 if (LineNo == 0) {
928 fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize);
929 }
930 }
931
932 //
933 // for framework vfr file
934 // adjust opcode sequence for uefi IFR format
935 // adjust inconsistent and varstore into the right position.
936 //
937 BOOLEAN
938 CIfrRecordInfoDB::CheckQuestionOpCode (
939 IN UINT8 OpCode
940 )
941 {
942 switch (OpCode) {
943 case EFI_IFR_CHECKBOX_OP:
944 case EFI_IFR_NUMERIC_OP:
945 case EFI_IFR_PASSWORD_OP:
946 case EFI_IFR_ONE_OF_OP:
947 case EFI_IFR_ACTION_OP:
948 case EFI_IFR_STRING_OP:
949 case EFI_IFR_DATE_OP:
950 case EFI_IFR_TIME_OP:
951 case EFI_IFR_ORDERED_LIST_OP:
952 return TRUE;
953 default:
954 return FALSE;
955 }
956 }
957
958 BOOLEAN
959 CIfrRecordInfoDB::CheckIdOpCode (
960 IN UINT8 OpCode
961 )
962 {
963 switch (OpCode) {
964 case EFI_IFR_EQ_ID_VAL_OP:
965 case EFI_IFR_EQ_ID_ID_OP:
966 case EFI_IFR_EQ_ID_VAL_LIST_OP:
967 case EFI_IFR_QUESTION_REF1_OP:
968 return TRUE;
969 default:
970 return FALSE;
971 }
972 }
973
974 EFI_QUESTION_ID
975 CIfrRecordInfoDB::GetOpcodeQuestionId (
976 IN EFI_IFR_OP_HEADER *OpHead
977 )
978 {
979 EFI_IFR_QUESTION_HEADER *QuestionHead;
980
981 QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1);
982
983 return QuestionHead->QuestionId;
984 }
985
986 EFI_VFR_RETURN_CODE
987 CIfrRecordInfoDB::IfrRecordAdjust (
988 VOID
989 )
990 {
991 SIfrRecord *pNode, *preNode;
992 SIfrRecord *uNode, *tNode;
993 EFI_IFR_OP_HEADER *OpHead, *tOpHead;
994 EFI_QUESTION_ID QuestionId;
995 UINT32 StackCount;
996 UINT32 QuestionScope;
997 UINT32 OpcodeOffset;
998 CHAR8 ErrorMsg[MAX_STRING_LEN] = {0, };
999 EFI_VFR_RETURN_CODE Status;
1000
1001 //
1002 // Init local variable
1003 //
1004 Status = VFR_RETURN_SUCCESS;
1005 pNode = mIfrRecordListHead;
1006 preNode = pNode;
1007 QuestionScope = 0;
1008 while (pNode != NULL) {
1009 OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;
1010
1011 //
1012 // make sure the inconsistent opcode in question scope
1013 //
1014 if (QuestionScope > 0) {
1015 QuestionScope += OpHead->Scope;
1016 if (OpHead->OpCode == EFI_IFR_END_OP) {
1017 QuestionScope --;
1018 }
1019 }
1020
1021 if (CheckQuestionOpCode (OpHead->OpCode)) {
1022 QuestionScope = 1;
1023 }
1024 //
1025 // for the inconsistent opcode not in question scope, adjust it
1026 //
1027 if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) {
1028 //
1029 // for inconsistent opcode not in question scope
1030 //
1031
1032 //
1033 // Count inconsistent opcode Scope
1034 //
1035 StackCount = OpHead->Scope;
1036 QuestionId = EFI_QUESTION_ID_INVALID;
1037 tNode = pNode;
1038 while (tNode != NULL && StackCount > 0) {
1039 tNode = tNode->mNext;
1040 tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf;
1041 //
1042 // Calculate Scope Number
1043 //
1044 StackCount += tOpHead->Scope;
1045 if (tOpHead->OpCode == EFI_IFR_END_OP) {
1046 StackCount --;
1047 }
1048 //
1049 // by IdEqual opcode to get QuestionId
1050 //
1051 if (QuestionId == EFI_QUESTION_ID_INVALID &&
1052 CheckIdOpCode (tOpHead->OpCode)) {
1053 QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1);
1054 }
1055 }
1056 if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) {
1057 //
1058 // report error; not found
1059 //
1060 sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId);
1061 gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
1062 Status = VFR_RETURN_MISMATCHED;
1063 break;
1064 }
1065 //
1066 // extract inconsistent opcode list
1067 // pNode is Incosistent opcode, tNode is End Opcode
1068 //
1069
1070 //
1071 // insert inconsistent opcode list into the right question scope by questionid
1072 //
1073 for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) {
1074 tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf;
1075 if (CheckQuestionOpCode (tOpHead->OpCode) &&
1076 (QuestionId == GetOpcodeQuestionId (tOpHead))) {
1077 break;
1078 }
1079 }
1080 //
1081 // insert inconsistent opcode list and check LATE_CHECK flag
1082 //
1083 if (uNode != NULL) {
1084 if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) {
1085 //
1086 // if LATE_CHECK flag is set, change inconsistent to nosumbit
1087 //
1088 OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP;
1089 }
1090
1091 //
1092 // skip the default storage for Date and Time
1093 //
1094 if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) {
1095 uNode = uNode->mNext;
1096 }
1097
1098 preNode->mNext = tNode->mNext;
1099 tNode->mNext = uNode->mNext;
1100 uNode->mNext = pNode;
1101 //
1102 // reset pNode to head list, scan the whole list again.
1103 //
1104 pNode = mIfrRecordListHead;
1105 preNode = pNode;
1106 QuestionScope = 0;
1107 continue;
1108 } else {
1109 //
1110 // not found matched question id, report error
1111 //
1112 sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId);
1113 gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);
1114 Status = VFR_RETURN_MISMATCHED;
1115 break;
1116 }
1117 } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP ||
1118 OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) {
1119 //
1120 // for new added group of varstore opcode
1121 //
1122 tNode = pNode;
1123 while (tNode->mNext != NULL) {
1124 tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf;
1125 if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP &&
1126 tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) {
1127 break;
1128 }
1129 tNode = tNode->mNext;
1130 }
1131
1132 if (tNode->mNext == NULL) {
1133 //
1134 // invalid IfrCode, IfrCode end by EndOpCode
1135 //
1136 gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end");
1137 Status = VFR_RETURN_MISMATCHED;
1138 break;
1139 }
1140
1141 if (tOpHead->OpCode != EFI_IFR_END_OP) {
1142 //
1143 // not new added varstore, which are not needed to be adjust.
1144 //
1145 preNode = tNode;
1146 pNode = tNode->mNext;
1147 continue;
1148 } else {
1149 //
1150 // move new added varstore opcode to the position befor form opcode
1151 // varstore opcode between pNode and tNode
1152 //
1153
1154 //
1155 // search form opcode from begin
1156 //
1157 for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) {
1158 tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf;
1159 if (tOpHead->OpCode == EFI_IFR_FORM_OP) {
1160 break;
1161 }
1162 }
1163 //
1164 // Insert varstore opcode beform form opcode if form opcode is found
1165 //
1166 if (uNode->mNext != NULL) {
1167 preNode->mNext = tNode->mNext;
1168 tNode->mNext = uNode->mNext;
1169 uNode->mNext = pNode;
1170 //
1171 // reset pNode to head list, scan the whole list again.
1172 //
1173 pNode = mIfrRecordListHead;
1174 preNode = pNode;
1175 QuestionScope = 0;
1176 continue;
1177 } else {
1178 //
1179 // not found form, continue scan IfrRecord list
1180 //
1181 preNode = tNode;
1182 pNode = tNode->mNext;
1183 continue;
1184 }
1185 }
1186 }
1187 //
1188 // next node
1189 //
1190 preNode = pNode;
1191 pNode = pNode->mNext;
1192 }
1193
1194 //
1195 // Update Ifr Opcode Offset
1196 //
1197 if (Status == VFR_RETURN_SUCCESS) {
1198 OpcodeOffset = 0;
1199 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {
1200 pNode->mOffset = OpcodeOffset;
1201 OpcodeOffset += pNode->mBinBufLen;
1202 }
1203 }
1204 return Status;
1205 }
1206
1207 CIfrRecordInfoDB gCIfrRecordInfoDB;
1208
1209 VOID
1210 CIfrObj::_EMIT_PENDING_OBJ (
1211 VOID
1212 )
1213 {
1214 CHAR8 *ObjBinBuf = NULL;
1215
1216 //
1217 // do nothing
1218 //
1219 if (!mDelayEmit || !gCreateOp) {
1220 return;
1221 }
1222
1223 mPkgOffset = gCFormPkg.GetPkgLength ();
1224 //
1225 // update data buffer to package data
1226 //
1227 ObjBinBuf = gCFormPkg.IfrBinBufferGet (mObjBinLen);
1228 if (ObjBinBuf != NULL) {
1229 memcpy (ObjBinBuf, mObjBinBuf, mObjBinLen);
1230 }
1231
1232 //
1233 // update bin buffer to package data buffer
1234 //
1235 if (mObjBinBuf != NULL) {
1236 delete mObjBinBuf;
1237 mObjBinBuf = ObjBinBuf;
1238 }
1239
1240 mDelayEmit = FALSE;
1241 }
1242
1243 /*
1244 * The definition of CIfrObj's member function
1245 */
1246 static struct {
1247 UINT8 mSize;
1248 UINT8 mScope;
1249 } gOpcodeSizesScopeTable[] = {
1250 { 0, 0 }, // EFI_IFR_INVALID - 0x00
1251 { sizeof (EFI_IFR_FORM), 1 }, // EFI_IFR_FORM_OP
1252 { sizeof (EFI_IFR_SUBTITLE), 1 }, // EFI_IFR_SUBTITLE_OP
1253 { sizeof (EFI_IFR_TEXT), 0 }, // EFI_IFR_TEXT_OP
1254 { sizeof (EFI_IFR_IMAGE), 0 }, // EFI_IFR_IMAGE_OP
1255 { sizeof (EFI_IFR_ONE_OF), 1 }, // EFI_IFR_ONE_OF_OP - 0x05
1256 { sizeof (EFI_IFR_CHECKBOX), 1}, // EFI_IFR_CHECKBOX_OP
1257 { sizeof (EFI_IFR_NUMERIC), 1 }, // EFI_IFR_NUMERIC_OP
1258 { sizeof (EFI_IFR_PASSWORD), 1 }, // EFI_IFR_PASSWORD_OP
1259 { sizeof (EFI_IFR_ONE_OF_OPTION), 0 }, // EFI_IFR_ONE_OF_OPTION_OP
1260 { sizeof (EFI_IFR_SUPPRESS_IF), 1 }, // EFI_IFR_SUPPRESS_IF - 0x0A
1261 { sizeof (EFI_IFR_LOCKED), 0 }, // EFI_IFR_LOCKED_OP
1262 { sizeof (EFI_IFR_ACTION), 1 }, // EFI_IFR_ACTION_OP
1263 { sizeof (EFI_IFR_RESET_BUTTON), 1 }, // EFI_IFR_RESET_BUTTON_OP
1264 { sizeof (EFI_IFR_FORM_SET), 1 }, // EFI_IFR_FORM_SET_OP -0xE
1265 { sizeof (EFI_IFR_REF), 0 }, // EFI_IFR_REF_OP
1266 { sizeof (EFI_IFR_NO_SUBMIT_IF), 1}, // EFI_IFR_NO_SUBMIT_IF_OP -0x10
1267 { sizeof (EFI_IFR_INCONSISTENT_IF), 1 }, // EFI_IFR_INCONSISTENT_IF_OP
1268 { sizeof (EFI_IFR_EQ_ID_VAL), 0 }, // EFI_IFR_EQ_ID_VAL_OP
1269 { sizeof (EFI_IFR_EQ_ID_ID), 0 }, // EFI_IFR_EQ_ID_ID_OP
1270 { sizeof (EFI_IFR_EQ_ID_VAL_LIST), 0 }, // EFI_IFR_EQ_ID_LIST_OP - 0x14
1271 { sizeof (EFI_IFR_AND), 0 }, // EFI_IFR_AND_OP
1272 { sizeof (EFI_IFR_OR), 0 }, // EFI_IFR_OR_OP
1273 { sizeof (EFI_IFR_NOT), 0 }, // EFI_IFR_NOT_OP
1274 { sizeof (EFI_IFR_RULE), 1 }, // EFI_IFR_RULE_OP
1275 { sizeof (EFI_IFR_GRAY_OUT_IF), 1 }, // EFI_IFR_GRAYOUT_IF_OP - 0x19
1276 { sizeof (EFI_IFR_DATE), 1 }, // EFI_IFR_DATE_OP
1277 { sizeof (EFI_IFR_TIME), 1 }, // EFI_IFR_TIME_OP
1278 { sizeof (EFI_IFR_STRING), 1 }, // EFI_IFR_STRING_OP
1279 { sizeof (EFI_IFR_REFRESH), 0 }, // EFI_IFR_REFRESH_OP
1280 { sizeof (EFI_IFR_DISABLE_IF), 1 }, // EFI_IFR_DISABLE_IF_OP - 0x1E
1281 { 0, 0 }, // 0x1F
1282 { sizeof (EFI_IFR_TO_LOWER), 0 }, // EFI_IFR_TO_LOWER_OP - 0x20
1283 { sizeof (EFI_IFR_TO_UPPER), 0 }, // EFI_IFR_TO_UPPER_OP - 0x21
1284 { sizeof (EFI_IFR_MAP), 1 }, // EFI_IFR_MAP - 0x22
1285 { sizeof (EFI_IFR_ORDERED_LIST), 1 }, // EFI_IFR_ORDERED_LIST_OP - 0x23
1286 { sizeof (EFI_IFR_VARSTORE), 0 }, // EFI_IFR_VARSTORE_OP
1287 { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP
1288 { sizeof (EFI_IFR_VARSTORE_EFI), 0 }, // EFI_IFR_VARSTORE_EFI_OP
1289 { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 }, // EFI_IFR_VARSTORE_DEVICE_OP
1290 { sizeof (EFI_IFR_VERSION), 0 }, // EFI_IFR_VERSION_OP - 0x28
1291 { sizeof (EFI_IFR_END), 0 }, // EFI_IFR_END_OP
1292 { sizeof (EFI_IFR_MATCH), 0 }, // EFI_IFR_MATCH_OP - 0x2A
1293 { sizeof (EFI_IFR_GET), 0 }, // EFI_IFR_GET - 0x2B
1294 { sizeof (EFI_IFR_SET), 0 }, // EFI_IFR_SET - 0x2C
1295 { sizeof (EFI_IFR_READ), 0 }, // EFI_IFR_READ - 0x2D
1296 { sizeof (EFI_IFR_WRITE), 0 }, // EFI_IFR_WRITE - 0x2E
1297 { sizeof (EFI_IFR_EQUAL), 0 }, // EFI_IFR_EQUAL_OP - 0x2F
1298 { sizeof (EFI_IFR_NOT_EQUAL), 0 }, // EFI_IFR_NOT_EQUAL_OP
1299 { sizeof (EFI_IFR_GREATER_THAN), 0 }, // EFI_IFR_GREATER_THAN_OP
1300 { sizeof (EFI_IFR_GREATER_EQUAL), 0 }, // EFI_IFR_GREATER_EQUAL_OP
1301 { sizeof (EFI_IFR_LESS_THAN), 0 }, // EFI_IFR_LESS_THAN_OP
1302 { sizeof (EFI_IFR_LESS_EQUAL), 0 }, // EFI_IFR_LESS_EQUAL_OP - 0x34
1303 { sizeof (EFI_IFR_BITWISE_AND), 0 }, // EFI_IFR_BITWISE_AND_OP
1304 { sizeof (EFI_IFR_BITWISE_OR), 0 }, // EFI_IFR_BITWISE_OR_OP
1305 { sizeof (EFI_IFR_BITWISE_NOT), 0 }, // EFI_IFR_BITWISE_NOT_OP
1306 { sizeof (EFI_IFR_SHIFT_LEFT), 0 }, // EFI_IFR_SHIFT_LEFT_OP
1307 { sizeof (EFI_IFR_SHIFT_RIGHT), 0 }, // EFI_IFR_SHIFT_RIGHT_OP
1308 { sizeof (EFI_IFR_ADD), 0 }, // EFI_IFR_ADD_OP - 0x3A
1309 { sizeof (EFI_IFR_SUBTRACT), 0 }, // EFI_IFR_SUBTRACT_OP
1310 { sizeof (EFI_IFR_MULTIPLY), 0 }, // EFI_IFR_MULTIPLY_OP
1311 { sizeof (EFI_IFR_DIVIDE), 0 }, // EFI_IFR_DIVIDE_OP
1312 { sizeof (EFI_IFR_MODULO), 0 }, // EFI_IFR_MODULO_OP - 0x3E
1313 { sizeof (EFI_IFR_RULE_REF), 0 }, // EFI_IFR_RULE_REF_OP
1314 { sizeof (EFI_IFR_QUESTION_REF1), 0 }, // EFI_IFR_QUESTION_REF1_OP
1315 { sizeof (EFI_IFR_QUESTION_REF2), 0 }, // EFI_IFR_QUESTION_REF2_OP - 0x41
1316 { sizeof (EFI_IFR_UINT8), 0}, // EFI_IFR_UINT8
1317 { sizeof (EFI_IFR_UINT16), 0}, // EFI_IFR_UINT16
1318 { sizeof (EFI_IFR_UINT32), 0}, // EFI_IFR_UINT32
1319 { sizeof (EFI_IFR_UINT64), 0}, // EFI_IFR_UTNT64
1320 { sizeof (EFI_IFR_TRUE), 0 }, // EFI_IFR_TRUE_OP - 0x46
1321 { sizeof (EFI_IFR_FALSE), 0 }, // EFI_IFR_FALSE_OP
1322 { sizeof (EFI_IFR_TO_UINT), 0 }, // EFI_IFR_TO_UINT_OP
1323 { sizeof (EFI_IFR_TO_STRING), 0 }, // EFI_IFR_TO_STRING_OP
1324 { sizeof (EFI_IFR_TO_BOOLEAN), 0 }, // EFI_IFR_TO_BOOLEAN_OP
1325 { sizeof (EFI_IFR_MID), 0 }, // EFI_IFR_MID_OP
1326 { sizeof (EFI_IFR_FIND), 0 }, // EFI_IFR_FIND_OP
1327 { sizeof (EFI_IFR_TOKEN), 0 }, // EFI_IFR_TOKEN_OP
1328 { sizeof (EFI_IFR_STRING_REF1), 0 }, // EFI_IFR_STRING_REF1_OP - 0x4E
1329 { sizeof (EFI_IFR_STRING_REF2), 0 }, // EFI_IFR_STRING_REF2_OP
1330 { sizeof (EFI_IFR_CONDITIONAL), 0 }, // EFI_IFR_CONDITIONAL_OP
1331 { sizeof (EFI_IFR_QUESTION_REF3), 0 }, // EFI_IFR_QUESTION_REF3_OP
1332 { sizeof (EFI_IFR_ZERO), 0 }, // EFI_IFR_ZERO_OP
1333 { sizeof (EFI_IFR_ONE), 0 }, // EFI_IFR_ONE_OP
1334 { sizeof (EFI_IFR_ONES), 0 }, // EFI_IFR_ONES_OP
1335 { sizeof (EFI_IFR_UNDEFINED), 0 }, // EFI_IFR_UNDEFINED_OP
1336 { sizeof (EFI_IFR_LENGTH), 0 }, // EFI_IFR_LENGTH_OP
1337 { sizeof (EFI_IFR_DUP), 0 }, // EFI_IFR_DUP_OP - 0x57
1338 { sizeof (EFI_IFR_THIS), 0 }, // EFI_IFR_THIS_OP
1339 { sizeof (EFI_IFR_SPAN), 0 }, // EFI_IFR_SPAN_OP
1340 { sizeof (EFI_IFR_VALUE), 1 }, // EFI_IFR_VALUE_OP
1341 { sizeof (EFI_IFR_DEFAULT), 0 }, // EFI_IFR_DEFAULT_OP
1342 { sizeof (EFI_IFR_DEFAULTSTORE), 0 }, // EFI_IFR_DEFAULTSTORE_OP - 0x5C
1343 { sizeof (EFI_IFR_FORM_MAP), 1}, // EFI_IFR_FORM_MAP_OP - 0x5D
1344 { sizeof (EFI_IFR_CATENATE), 0 }, // EFI_IFR_CATENATE_OP
1345 { sizeof (EFI_IFR_GUID), 0 }, // EFI_IFR_GUID_OP
1346 { sizeof (EFI_IFR_SECURITY), 0 }, // EFI_IFR_SECURITY_OP - 0x60
1347 { sizeof (EFI_IFR_MODAL), 0}, // EFI_IFR_MODAL_OP - 0x61
1348 { sizeof (EFI_IFR_REFRESH_ID), 0}, // EFI_IFR_REFRESH_ID_OP - 0x62
1349 };
1350
1351 #ifdef CIFROBJ_DEUBG
1352 static struct {
1353 CHAR8 *mIfrName;
1354 } gIfrObjPrintDebugTable[] = {
1355 "EFI_IFR_INVALID", "EFI_IFR_FORM", "EFI_IFR_SUBTITLE", "EFI_IFR_TEXT", "EFI_IFR_IMAGE", "EFI_IFR_ONE_OF",
1356 "EFI_IFR_CHECKBOX", "EFI_IFR_NUMERIC", "EFI_IFR_PASSWORD", "EFI_IFR_ONE_OF_OPTION", "EFI_IFR_SUPPRESS_IF", "EFI_IFR_LOCKED",
1357 "EFI_IFR_ACTION", "EFI_IFR_RESET_BUTTON", "EFI_IFR_FORM_SET", "EFI_IFR_REF", "EFI_IFR_NO_SUBMIT_IF", "EFI_IFR_INCONSISTENT_IF",
1358 "EFI_IFR_EQ_ID_VAL", "EFI_IFR_EQ_ID_ID", "EFI_IFR_EQ_ID_LIST", "EFI_IFR_AND", "EFI_IFR_OR", "EFI_IFR_NOT",
1359 "EFI_IFR_RULE", "EFI_IFR_GRAY_OUT_IF", "EFI_IFR_DATE", "EFI_IFR_TIME", "EFI_IFR_STRING", "EFI_IFR_REFRESH",
1360 "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID", "EFI_IFR_TO_LOWER", "EFI_IFR_TO_UPPER", "EFI_IFR_MAP", "EFI_IFR_ORDERED_LIST",
1361 "EFI_IFR_VARSTORE", "EFI_IFR_VARSTORE_NAME_VALUE", "EFI_IFR_VARSTORE_EFI", "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION", "EFI_IFR_END",
1362 "EFI_IFR_MATCH", "EFI_IFR_GET", "EFI_IFR_SET", "EFI_IFR_READ", "EFI_IFR_WRITE", "EFI_IFR_EQUAL",
1363 "EFI_IFR_NOT_EQUAL", "EFI_IFR_GREATER_THAN", "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN", "EFI_IFR_LESS_EQUAL", "EFI_IFR_BITWISE_AND",
1364 "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT", "EFI_IFR_SHIFT_LEFT", "EFI_IFR_SHIFT_RIGHT", "EFI_IFR_ADD", "EFI_IFR_SUBTRACT",
1365 "EFI_IFR_MULTIPLY", "EFI_IFR_DIVIDE", "EFI_IFR_MODULO", "EFI_IFR_RULE_REF", "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2",
1366 "EFI_IFR_UINT8", "EFI_IFR_UINT16", "EFI_IFR_UINT32", "EFI_IFR_UINT64", "EFI_IFR_TRUE", "EFI_IFR_FALSE",
1367 "EFI_IFR_TO_UINT", "EFI_IFR_TO_STRING", "EFI_IFR_TO_BOOLEAN", "EFI_IFR_MID", "EFI_IFR_FIND", "EFI_IFR_TOKEN",
1368 "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2", "EFI_IFR_CONDITIONAL", "EFI_IFR_QUESTION_REF3", "EFI_IFR_ZERO", "EFI_IFR_ONE",
1369 "EFI_IFR_ONES", "EFI_IFR_UNDEFINED", "EFI_IFR_LENGTH", "EFI_IFR_DUP", "EFI_IFR_THIS", "EFI_IFR_SPAN",
1370 "EFI_IFR_VALUE", "EFI_IFR_DEFAULT", "EFI_IFR_DEFAULTSTORE", "EFI_IFR_FORM_MAP", "EFI_IFR_CATENATE", "EFI_IFR_GUID",
1371 "EFI_IFR_SECURITY", "EFI_IFR_MODAL", "EFI_IFR_REFRESH_ID",
1372 };
1373
1374 VOID
1375 CIFROBJ_DEBUG_PRINT (
1376 IN UINT8 OpCode
1377 )
1378 {
1379 printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName);
1380 }
1381 #else
1382
1383 #define CIFROBJ_DEBUG_PRINT(OpCode)
1384
1385 #endif
1386
1387 BOOLEAN gCreateOp = TRUE;
1388
1389 CIfrObj::CIfrObj (
1390 IN UINT8 OpCode,
1391 OUT CHAR8 **IfrObj,
1392 IN UINT8 ObjBinLen,
1393 IN BOOLEAN DelayEmit
1394 )
1395 {
1396 mDelayEmit = DelayEmit;
1397 mPkgOffset = gCFormPkg.GetPkgLength ();
1398 mObjBinLen = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen;
1399 mObjBinBuf = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH];
1400 mRecordIdx = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD;
1401
1402 if (IfrObj != NULL) {
1403 *IfrObj = mObjBinBuf;
1404 }
1405
1406 CIFROBJ_DEBUG_PRINT (OpCode);
1407 }
1408
1409 CIfrObj::~CIfrObj (
1410 VOID
1411 )
1412 {
1413 if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) {
1414 _EMIT_PENDING_OBJ ();
1415 }
1416
1417 gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset);
1418 }
1419
1420 /*
1421 * The definition of CIfrObj's member function
1422 */
1423 UINT8 gScopeCount = 0;
1424
1425 CIfrOpHeader::CIfrOpHeader (
1426 IN UINT8 OpCode,
1427 IN VOID *StartAddr,
1428 IN UINT8 Length
1429 ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr)
1430 {
1431 mHeader->OpCode = OpCode;
1432 mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length;
1433 mHeader->Scope = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0;
1434 }
1435
1436 CIfrOpHeader::CIfrOpHeader (
1437 IN CIfrOpHeader &OpHdr
1438 )
1439 {
1440 mHeader = OpHdr.mHeader;
1441 }
1442
1443 UINT32 CIfrFormId::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, };