BaseTools: resolve initialization order errors in VfrFormPkg.h
[mirror_edk2.git] / BaseTools / Source / C / VfrCompile / VfrFormPkg.cpp
CommitLineData
30fdf114
LG
1/** @file\r
2 \r
3 The definition of CFormPkg's member function\r
4\r
42c808d4 5Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
40d841f6 6This program and the accompanying materials \r
30fdf114
LG
7are licensed and made available under the terms and conditions of the BSD License \r
8which accompanies this distribution. The full text of the license may be found at \r
9http://opensource.org/licenses/bsd-license.php \r
10 \r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include "stdio.h"\r
9b78c54a 17#include "assert.h"\r
30fdf114
LG
18#include "VfrFormPkg.h"\r
19\r
20/*\r
21 * The definition of CFormPkg's member function\r
22 */\r
23\r
24SPendingAssign::SPendingAssign (\r
25 IN CHAR8 *Key, \r
26 IN VOID *Addr, \r
27 IN UINT32 Len, \r
28 IN UINT32 LineNo,\r
52302d4d 29 IN CONST CHAR8 *Msg\r
30fdf114
LG
30 )\r
31{\r
32 mKey = NULL;\r
33 mAddr = Addr;\r
34 mLen = Len;\r
35 mFlag = PENDING;\r
36 mLineNo = LineNo;\r
37 mMsg = NULL;\r
38 mNext = NULL;\r
39 if (Key != NULL) {\r
40 mKey = new CHAR8[strlen (Key) + 1];\r
41 if (mKey != NULL) {\r
42 strcpy (mKey, Key);\r
43 }\r
44 }\r
45\r
46 if (Msg != NULL) {\r
47 mMsg = new CHAR8[strlen (Msg) + 1];\r
48 if (mMsg != NULL) {\r
49 strcpy (mMsg, Msg);\r
50 }\r
51 }\r
52}\r
53\r
54SPendingAssign::~SPendingAssign (\r
55 VOID\r
56 )\r
57{\r
58 if (mKey != NULL) {\r
fd542523 59 delete[] mKey;\r
30fdf114
LG
60 }\r
61 mAddr = NULL;\r
62 mLen = 0;\r
63 mLineNo = 0;\r
64 if (mMsg != NULL) {\r
fd542523 65 delete[] mMsg;\r
30fdf114
LG
66 }\r
67 mNext = NULL;\r
68}\r
69\r
70VOID\r
71SPendingAssign::SetAddrAndLen (\r
72 IN VOID *Addr, \r
73 IN UINT32 LineNo\r
74 )\r
75{\r
76 mAddr = Addr;\r
77 mLineNo = LineNo;\r
78}\r
79\r
80VOID\r
81SPendingAssign::AssignValue (\r
82 IN VOID *Addr, \r
83 IN UINT32 Len\r
84 )\r
85{\r
f51461c8 86 memmove (mAddr, Addr, (mLen < Len ? mLen : Len));\r
30fdf114
LG
87 mFlag = ASSIGNED;\r
88}\r
89\r
90CHAR8 *\r
91SPendingAssign::GetKey (\r
92 VOID\r
93 )\r
94{\r
95 return mKey;\r
96}\r
97\r
98CFormPkg::CFormPkg (\r
ed395cfe 99 IN UINT32 BufferSize\r
30fdf114
LG
100 )\r
101{\r
102 CHAR8 *BufferStart;\r
103 CHAR8 *BufferEnd;\r
104 SBufferNode *Node;\r
105\r
106 mPkgLength = 0;\r
b748e35c 107 mBufferSize = 0;\r
30fdf114 108 mBufferNodeQueueHead = NULL;\r
b748e35c 109 mBufferNodeQueueTail = NULL;\r
30fdf114 110 mCurrBufferNode = NULL;\r
b748e35c
HW
111 mReadBufferNode = NULL;\r
112 mReadBufferOffset = 0;\r
113 PendingAssignList = NULL;\r
30fdf114
LG
114\r
115 Node = new SBufferNode;\r
116 if (Node == NULL) {\r
117 return ;\r
118 }\r
119 BufferStart = new CHAR8[BufferSize];\r
120 if (BufferStart == NULL) {\r
bdf5f731 121 delete Node;\r
30fdf114
LG
122 return;\r
123 }\r
124 BufferEnd = BufferStart + BufferSize;\r
125\r
126 memset (BufferStart, 0, BufferSize);\r
127 Node->mBufferStart = BufferStart;\r
128 Node->mBufferEnd = BufferEnd;\r
129 Node->mBufferFree = BufferStart;\r
130 Node->mNext = NULL;\r
131\r
132 mBufferSize = BufferSize;\r
133 mBufferNodeQueueHead = Node;\r
134 mBufferNodeQueueTail = Node;\r
135 mCurrBufferNode = Node;\r
136}\r
137\r
138CFormPkg::~CFormPkg ()\r
139{\r
140 SBufferNode *pBNode;\r
141 SPendingAssign *pPNode;\r
142\r
143 while (mBufferNodeQueueHead != NULL) {\r
144 pBNode = mBufferNodeQueueHead;\r
145 mBufferNodeQueueHead = mBufferNodeQueueHead->mNext;\r
146 if (pBNode->mBufferStart != NULL) {\r
147 delete pBNode->mBufferStart;\r
148 delete pBNode;\r
149 }\r
150 }\r
151 mBufferNodeQueueTail = NULL;\r
152 mCurrBufferNode = NULL;\r
153\r
154 while (PendingAssignList != NULL) {\r
155 pPNode = PendingAssignList;\r
156 PendingAssignList = PendingAssignList->mNext;\r
157 delete pPNode;\r
158 }\r
159 PendingAssignList = NULL;\r
160}\r
161\r
4afd3d04
LG
162SBufferNode *\r
163CFormPkg::CreateNewNode (\r
164 VOID\r
165 )\r
166{\r
167 SBufferNode *Node;\r
168\r
169 Node = new SBufferNode;\r
170 if (Node == NULL) {\r
171 return NULL;\r
172 }\r
173\r
174 Node->mBufferStart = new CHAR8[mBufferSize];\r
175 if (Node->mBufferStart == NULL) {\r
176 delete Node;\r
177 return NULL;\r
178 } else {\r
179 memset (Node->mBufferStart, 0, mBufferSize);\r
180 Node->mBufferEnd = Node->mBufferStart + mBufferSize;\r
181 Node->mBufferFree = Node->mBufferStart;\r
182 Node->mNext = NULL;\r
183 }\r
184\r
185 return Node;\r
186}\r
187\r
30fdf114
LG
188CHAR8 *\r
189CFormPkg::IfrBinBufferGet (\r
190 IN UINT32 Len\r
191 )\r
192{\r
4afd3d04
LG
193 CHAR8 *BinBuffer = NULL;\r
194 SBufferNode *Node = NULL;\r
30fdf114
LG
195\r
196 if ((Len == 0) || (Len > mBufferSize)) {\r
197 return NULL;\r
198 }\r
199\r
200 if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) {\r
201 BinBuffer = mCurrBufferNode->mBufferFree;\r
202 mCurrBufferNode->mBufferFree += Len;\r
203 } else {\r
4afd3d04 204 Node = CreateNewNode ();\r
30fdf114
LG
205 if (Node == NULL) {\r
206 return NULL;\r
207 }\r
208\r
30fdf114
LG
209 if (mBufferNodeQueueTail == NULL) {\r
210 mBufferNodeQueueHead = mBufferNodeQueueTail = Node;\r
211 } else {\r
212 mBufferNodeQueueTail->mNext = Node;\r
213 mBufferNodeQueueTail = Node;\r
214 }\r
215 mCurrBufferNode = Node;\r
216\r
217 //\r
218 // Now try again.\r
219 //\r
220 BinBuffer = mCurrBufferNode->mBufferFree;\r
221 mCurrBufferNode->mBufferFree += Len;\r
222 }\r
223\r
224 mPkgLength += Len;\r
225\r
226 return BinBuffer;\r
227}\r
228\r
229inline\r
230UINT32\r
231CFormPkg::GetPkgLength (\r
232 VOID\r
233 )\r
234{\r
235 return mPkgLength;\r
236}\r
237\r
238VOID\r
239CFormPkg::Open (\r
240 VOID\r
241 )\r
242{\r
243 mReadBufferNode = mBufferNodeQueueHead;\r
244 mReadBufferOffset = 0;\r
245}\r
246\r
247VOID\r
248CFormPkg::Close (\r
249 VOID\r
250 )\r
251{\r
252 mReadBufferNode = NULL;\r
253 mReadBufferOffset = 0;\r
254}\r
255\r
256UINT32\r
257CFormPkg::Read (\r
258 IN CHAR8 *Buffer, \r
259 IN UINT32 Size\r
260 )\r
261{\r
262 UINT32 Index;\r
263\r
264 if ((Size == 0) || (Buffer == NULL)) {\r
265 return 0;\r
266 }\r
267\r
268 if (mReadBufferNode == NULL) {\r
4afd3d04 269 return 0;\r
30fdf114
LG
270 }\r
271\r
272 for (Index = 0; Index < Size; Index++) {\r
273 if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) {\r
274 Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++];\r
275 } else {\r
276 if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) {\r
277 return Index;\r
278 } else {\r
279 mReadBufferOffset = 0;\r
4afd3d04 280 Index --;\r
30fdf114
LG
281 }\r
282 }\r
283 }\r
284\r
285 return Size;\r
286}\r
287\r
288EFI_VFR_RETURN_CODE\r
289CFormPkg::BuildPkgHdr (\r
290 OUT EFI_HII_PACKAGE_HEADER **PkgHdr\r
291 )\r
292{\r
293 if (PkgHdr == NULL) {\r
294 return VFR_RETURN_FATAL_ERROR;\r
295 }\r
296\r
297 if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) {\r
298 return VFR_RETURN_OUT_FOR_RESOURCES;\r
299 }\r
300\r
301 (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM;\r
302 (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER);\r
303\r
304 return VFR_RETURN_SUCCESS;\r
305}\r
306\r
307EFI_VFR_RETURN_CODE\r
308CFormPkg::BuildPkg (\r
309 OUT PACKAGE_DATA &TBuffer\r
310 )\r
311{\r
312 \r
313 CHAR8 *Temp;\r
314 UINT32 Size;\r
315 CHAR8 Buffer[1024];\r
316\r
317 if (TBuffer.Buffer != NULL) {\r
318 delete TBuffer.Buffer;\r
319 }\r
320\r
321 TBuffer.Size = mPkgLength;\r
322 TBuffer.Buffer = NULL;\r
323 if (TBuffer.Size != 0) {\r
324 TBuffer.Buffer = new CHAR8[TBuffer.Size];\r
325 } else {\r
326 return VFR_RETURN_SUCCESS;\r
327 }\r
328\r
329 Temp = TBuffer.Buffer;\r
330 Open ();\r
331 while ((Size = Read (Buffer, 1024)) != 0) {\r
332 memcpy (Temp, Buffer, Size);\r
333 Temp += Size;\r
334 }\r
335 Close ();\r
336 return VFR_RETURN_SUCCESS;\r
337}\r
338\r
339\r
340EFI_VFR_RETURN_CODE\r
341CFormPkg::BuildPkg (\r
342 IN FILE *Output,\r
343 IN PACKAGE_DATA *PkgData\r
344 )\r
345{\r
346 EFI_VFR_RETURN_CODE Ret;\r
347 CHAR8 Buffer[1024];\r
348 UINT32 Size;\r
349 EFI_HII_PACKAGE_HEADER *PkgHdr;\r
350\r
351 if (Output == NULL) {\r
352 return VFR_RETURN_FATAL_ERROR;\r
353 }\r
354\r
355 if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {\r
356 return Ret;\r
357 }\r
358 fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output);\r
359 delete PkgHdr;\r
360 \r
361 if (PkgData == NULL) {\r
362 Open ();\r
363 while ((Size = Read (Buffer, 1024)) != 0) {\r
364 fwrite (Buffer, Size, 1, Output);\r
365 }\r
366 Close ();\r
367 } else {\r
368 fwrite (PkgData->Buffer, PkgData->Size, 1, Output);\r
369 }\r
370\r
371 return VFR_RETURN_SUCCESS;\r
372}\r
373\r
374VOID\r
375CFormPkg::_WRITE_PKG_LINE (\r
52302d4d
LG
376 IN FILE *pFile,\r
377 IN UINT32 LineBytes,\r
378 IN CONST CHAR8 *LineHeader,\r
379 IN CHAR8 *BlkBuf,\r
380 IN UINT32 BlkSize\r
30fdf114
LG
381 )\r
382{\r
383 UINT32 Index;\r
384\r
385 if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {\r
386 return;\r
387 }\r
388\r
389 for (Index = 0; Index < BlkSize; Index++) {\r
390 if ((Index % LineBytes) == 0) {\r
391 fprintf (pFile, "\n%s", LineHeader);\r
392 }\r
393 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);\r
394 }\r
395}\r
396\r
397VOID\r
398CFormPkg::_WRITE_PKG_END (\r
52302d4d
LG
399 IN FILE *pFile,\r
400 IN UINT32 LineBytes,\r
401 IN CONST CHAR8 *LineHeader,\r
402 IN CHAR8 *BlkBuf,\r
403 IN UINT32 BlkSize\r
30fdf114
LG
404 )\r
405{\r
406 UINT32 Index;\r
407\r
408 if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {\r
409 return;\r
410 }\r
411\r
412 for (Index = 0; Index < BlkSize - 1; Index++) {\r
413 if ((Index % LineBytes) == 0) {\r
414 fprintf (pFile, "\n%s", LineHeader);\r
415 }\r
416 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);\r
417 }\r
418\r
419 if ((Index % LineBytes) == 0) {\r
420 fprintf (pFile, "\n%s", LineHeader);\r
421 }\r
422 fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);\r
423}\r
424\r
425#define BYTES_PRE_LINE 0x10\r
4afd3d04
LG
426UINT32 gAdjustOpcodeOffset = 0;\r
427BOOLEAN gNeedAdjustOpcode = FALSE;\r
428UINT32 gAdjustOpcodeLen = 0;\r
30fdf114
LG
429\r
430EFI_VFR_RETURN_CODE \r
431CFormPkg::GenCFile (\r
432 IN CHAR8 *BaseName,\r
433 IN FILE *pFile,\r
434 IN PACKAGE_DATA *PkgData\r
435 )\r
436{\r
437 EFI_VFR_RETURN_CODE Ret;\r
438 CHAR8 Buffer[BYTES_PRE_LINE * 8];\r
439 EFI_HII_PACKAGE_HEADER *PkgHdr;\r
440 UINT32 PkgLength = 0;\r
441 UINT32 ReadSize = 0;\r
442\r
443 if ((BaseName == NULL) || (pFile == NULL)) {\r
444 return VFR_RETURN_FATAL_ERROR;\r
445 }\r
446\r
447 fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName);\r
448\r
449 if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) {\r
450 return Ret;\r
451 }\r
452\r
453 //\r
454 // For framework vfr file, the extension framework header will be added.\r
455 //\r
456 if (VfrCompatibleMode) {\r
457 fprintf (pFile, " // FRAMEWORK PACKAGE HEADER Length\n");\r
458 PkgLength = PkgHdr->Length + sizeof (UINT32) + 2;\r
459 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32)); \r
460 fprintf (pFile, "\n\n // FRAMEWORK PACKAGE HEADER Type\n");\r
461 PkgLength = 3;\r
462 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT16)); \r
463 } else {\r
464 fprintf (pFile, " // ARRAY LENGTH\n");\r
465 PkgLength = PkgHdr->Length + sizeof (UINT32);\r
466 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32)); \r
467 }\r
468\r
469 fprintf (pFile, "\n\n // PACKAGE HEADER\n");\r
470 _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
471 PkgLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
472\r
473 fprintf (pFile, "\n\n // PACKAGE DATA\n");\r
474 \r
475 if (PkgData == NULL) {\r
476 Open ();\r
477 while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) {\r
478 PkgLength += ReadSize;\r
479 if (PkgLength < PkgHdr->Length) {\r
480 _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize);\r
481 } else {\r
482 _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize);\r
483 }\r
484 }\r
485 Close ();\r
486 } else {\r
487 if (PkgData->Size % BYTES_PRE_LINE != 0) {\r
488 PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE);\r
489 _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength);\r
490 _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE);\r
491 } else {\r
492 PkgLength = PkgData->Size - BYTES_PRE_LINE;\r
493 _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength);\r
494 _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE);\r
495 }\r
496 }\r
497\r
498 delete PkgHdr;\r
499 fprintf (pFile, "\n};\n");\r
500\r
501 return VFR_RETURN_SUCCESS;\r
502}\r
503\r
504EFI_VFR_RETURN_CODE\r
505CFormPkg::AssignPending (\r
506 IN CHAR8 *Key, \r
507 IN VOID *ValAddr, \r
508 IN UINT32 ValLen,\r
509 IN UINT32 LineNo,\r
52302d4d 510 IN CONST CHAR8 *Msg\r
30fdf114
LG
511 )\r
512{\r
513 SPendingAssign *pNew;\r
514\r
515 pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg);\r
516 if (pNew == NULL) {\r
517 return VFR_RETURN_OUT_FOR_RESOURCES;\r
518 }\r
519\r
520 pNew->mNext = PendingAssignList;\r
521 PendingAssignList = pNew;\r
522 return VFR_RETURN_SUCCESS;\r
523}\r
524\r
525VOID\r
526CFormPkg::DoPendingAssign (\r
527 IN CHAR8 *Key, \r
528 IN VOID *ValAddr, \r
529 IN UINT32 ValLen\r
530 )\r
531{\r
532 SPendingAssign *pNode;\r
533\r
534 if ((Key == NULL) || (ValAddr == NULL)) {\r
535 return;\r
536 }\r
537\r
538 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {\r
539 if (strcmp (pNode->mKey, Key) == 0) {\r
540 pNode->AssignValue (ValAddr, ValLen);\r
541 }\r
542 }\r
543}\r
544\r
545bool\r
546CFormPkg::HavePendingUnassigned (\r
547 VOID\r
548 )\r
549{\r
550 SPendingAssign *pNode;\r
551\r
552 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {\r
553 if (pNode->mFlag == PENDING) {\r
554 return TRUE;\r
555 }\r
556 }\r
557\r
558 return FALSE;\r
559}\r
560\r
561VOID\r
562CFormPkg::PendingAssignPrintAll (\r
563 VOID\r
564 )\r
565{\r
566 SPendingAssign *pNode;\r
567\r
568 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {\r
569 if (pNode->mFlag == PENDING) {\r
570 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg);\r
571 }\r
572 }\r
573}\r
574\r
4afd3d04
LG
575SBufferNode *\r
576CFormPkg::GetBinBufferNodeForAddr (\r
577 IN CHAR8 *BinBuffAddr\r
578 )\r
579{\r
580 SBufferNode *TmpNode;\r
581\r
582 TmpNode = mBufferNodeQueueHead;\r
583\r
584 while (TmpNode != NULL) {\r
585 if (TmpNode->mBufferStart <= BinBuffAddr && TmpNode->mBufferFree >= BinBuffAddr) {\r
586 return TmpNode;\r
587 }\r
588\r
589 TmpNode = TmpNode->mNext;\r
590 }\r
591\r
592 return NULL;\r
593}\r
594\r
595SBufferNode *\r
596CFormPkg::GetNodeBefore(\r
597 IN SBufferNode *CurrentNode\r
598 )\r
599{\r
600 SBufferNode *FirstNode = mBufferNodeQueueHead;\r
601 SBufferNode *LastNode = mBufferNodeQueueHead;\r
602\r
603 while (FirstNode != NULL) {\r
604 if (FirstNode == CurrentNode) {\r
605 break;\r
606 }\r
607\r
608 LastNode = FirstNode;\r
609 FirstNode = FirstNode->mNext;\r
610 }\r
611\r
612 if (FirstNode == NULL) {\r
613 LastNode = NULL;\r
614 }\r
615\r
616 return LastNode;\r
617}\r
618\r
619EFI_VFR_RETURN_CODE\r
620CFormPkg::InsertNodeBefore(\r
621 IN SBufferNode *CurrentNode,\r
622 IN SBufferNode *NewNode\r
623 )\r
624{\r
625 SBufferNode *LastNode = GetNodeBefore (CurrentNode);\r
626\r
627 if (LastNode == NULL) {\r
628 return VFR_RETURN_MISMATCHED;\r
629 }\r
630\r
631 NewNode->mNext = LastNode->mNext;\r
632 LastNode->mNext = NewNode;\r
633\r
634 return VFR_RETURN_SUCCESS;\r
635}\r
636\r
637CHAR8 *\r
638CFormPkg::GetBufAddrBaseOnOffset (\r
639 IN UINT32 Offset\r
640 )\r
641{\r
642 SBufferNode *TmpNode;\r
643 UINT32 TotalBufLen;\r
644 UINT32 CurrentBufLen;\r
645\r
646 TotalBufLen = 0;\r
647\r
648 for (TmpNode = mBufferNodeQueueHead; TmpNode != NULL; TmpNode = TmpNode->mNext) {\r
649 CurrentBufLen = TmpNode->mBufferFree - TmpNode->mBufferStart;\r
650 if (Offset >= TotalBufLen && Offset < TotalBufLen + CurrentBufLen) {\r
651 return TmpNode->mBufferStart + (Offset - TotalBufLen);\r
652 }\r
653\r
654 TotalBufLen += CurrentBufLen;\r
655 }\r
656\r
657 return NULL;\r
658}\r
659\r
660EFI_VFR_RETURN_CODE\r
661CFormPkg::AdjustDynamicInsertOpcode (\r
74bbe31b
DB
662 IN CHAR8 *InserPositionAddr,\r
663 IN CHAR8 *InsertOpcodeAddr,\r
664 IN BOOLEAN CreateOpcodeAfterParsingVfr\r
4afd3d04
LG
665 )\r
666{\r
74bbe31b 667 SBufferNode *InserPositionNode;\r
4afd3d04
LG
668 SBufferNode *InsertOpcodeNode;\r
669 SBufferNode *NewRestoreNodeBegin;\r
670 SBufferNode *NewRestoreNodeEnd;\r
671 SBufferNode *NewLastEndNode;\r
672 SBufferNode *TmpNode;\r
673 UINT32 NeedRestoreCodeLen;\r
674\r
675 NewRestoreNodeEnd = NULL;\r
676\r
74bbe31b 677 InserPositionNode = GetBinBufferNodeForAddr(InserPositionAddr);\r
4afd3d04 678 InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr);\r
9b78c54a
HW
679 assert (InserPositionNode != NULL);\r
680 assert (InsertOpcodeNode != NULL);\r
4afd3d04 681\r
74bbe31b 682 if (InserPositionNode == InsertOpcodeNode) {\r
4afd3d04
LG
683 //\r
684 // Create New Node to save the restore opcode.\r
685 //\r
74bbe31b 686 NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr;\r
4afd3d04
LG
687 gAdjustOpcodeLen = NeedRestoreCodeLen;\r
688 NewRestoreNodeBegin = CreateNewNode ();\r
689 if (NewRestoreNodeBegin == NULL) {\r
690 return VFR_RETURN_OUT_FOR_RESOURCES;\r
691 }\r
74bbe31b 692 memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);\r
4afd3d04
LG
693 NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;\r
694\r
695 //\r
696 // Override the restore buffer data.\r
697 //\r
74bbe31b 698 memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);\r
4afd3d04
LG
699 InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen;\r
700 memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen);\r
701 } else {\r
702 //\r
703 // Create New Node to save the restore opcode.\r
704 //\r
74bbe31b 705 NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr;\r
4afd3d04
LG
706 gAdjustOpcodeLen = NeedRestoreCodeLen;\r
707 NewRestoreNodeBegin = CreateNewNode ();\r
708 if (NewRestoreNodeBegin == NULL) {\r
709 return VFR_RETURN_OUT_FOR_RESOURCES;\r
710 }\r
74bbe31b 711 memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen);\r
4afd3d04
LG
712 NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen;\r
713 //\r
714 // Override the restore buffer data.\r
715 //\r
74bbe31b 716 InserPositionNode->mBufferFree -= NeedRestoreCodeLen;\r
4afd3d04
LG
717 //\r
718 // Link the restore data to new node.\r
719 //\r
74bbe31b 720 NewRestoreNodeBegin->mNext = InserPositionNode->mNext;\r
4afd3d04
LG
721\r
722 //\r
723 // Count the Adjust opcode len.\r
724 //\r
74bbe31b 725 TmpNode = InserPositionNode->mNext;\r
4afd3d04
LG
726 while (TmpNode != InsertOpcodeNode) {\r
727 gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart;\r
728 TmpNode = TmpNode->mNext;\r
729 }\r
730\r
731 //\r
732 // Create New Node to save the last node of restore opcode.\r
733 //\r
734 NeedRestoreCodeLen = InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;\r
735 gAdjustOpcodeLen += NeedRestoreCodeLen;\r
736 if (NeedRestoreCodeLen > 0) {\r
737 NewRestoreNodeEnd = CreateNewNode ();\r
738 if (NewRestoreNodeEnd == NULL) {\r
739 return VFR_RETURN_OUT_FOR_RESOURCES;\r
740 }\r
741 memcpy (NewRestoreNodeEnd->mBufferFree, InsertOpcodeNode->mBufferStart, NeedRestoreCodeLen);\r
742 NewRestoreNodeEnd->mBufferFree += NeedRestoreCodeLen;\r
743 //\r
744 // Override the restore buffer data.\r
745 //\r
f51461c8 746 memmove (InsertOpcodeNode->mBufferStart, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr);\r
4afd3d04
LG
747 InsertOpcodeNode->mBufferFree -= InsertOpcodeAddr - InsertOpcodeNode->mBufferStart;\r
748\r
749 //\r
750 // Insert the last restore data node.\r
751 //\r
752 TmpNode = GetNodeBefore (InsertOpcodeNode);\r
9b78c54a
HW
753 assert (TmpNode != NULL);\r
754\r
74bbe31b 755 if (TmpNode == InserPositionNode) {\r
4afd3d04
LG
756 NewRestoreNodeBegin->mNext = NewRestoreNodeEnd;\r
757 } else {\r
758 TmpNode->mNext = NewRestoreNodeEnd;\r
759 }\r
760 //\r
74bbe31b 761 // Connect the dynamic opcode node to the node after InserPositionNode.\r
4afd3d04 762 //\r
74bbe31b 763 InserPositionNode->mNext = InsertOpcodeNode;\r
4afd3d04
LG
764 }\r
765 }\r
766\r
74bbe31b 767 if (CreateOpcodeAfterParsingVfr) {\r
4afd3d04 768 //\r
74bbe31b
DB
769 // Th new opcodes were created after Parsing Vfr file,\r
770 // so the content in mBufferNodeQueueTail must be the new created opcodes.\r
771 // So connet the NewRestoreNodeBegin to the tail and update the tail node.\r
4afd3d04 772 //\r
4afd3d04
LG
773 mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;\r
774 if (NewRestoreNodeEnd != NULL) {\r
74bbe31b 775 mBufferNodeQueueTail = NewRestoreNodeEnd;\r
4afd3d04 776 } else {\r
74bbe31b 777 mBufferNodeQueueTail = NewRestoreNodeBegin;\r
4afd3d04 778 }\r
74bbe31b
DB
779 } else {\r
780 if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) {\r
781 //\r
782 // End form set opcode all in the mBufferNodeQueueTail node.\r
783 //\r
784 NewLastEndNode = CreateNewNode ();\r
785 if (NewLastEndNode == NULL) {\r
786 return VFR_RETURN_OUT_FOR_RESOURCES;\r
787 }\r
788 NewLastEndNode->mBufferStart[0] = 0x29;\r
789 NewLastEndNode->mBufferStart[1] = 0x02;\r
790 NewLastEndNode->mBufferFree += 2;\r
4afd3d04 791\r
74bbe31b
DB
792 mBufferNodeQueueTail->mBufferFree -= 2;\r
793\r
794 mBufferNodeQueueTail->mNext = NewRestoreNodeBegin;\r
795 if (NewRestoreNodeEnd != NULL) {\r
796 NewRestoreNodeEnd->mNext = NewLastEndNode;\r
797 } else {\r
798 NewRestoreNodeBegin->mNext = NewLastEndNode;\r
799 }\r
800\r
801 mBufferNodeQueueTail = NewLastEndNode;\r
802 } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) {\r
803 TmpNode = GetNodeBefore(mBufferNodeQueueTail);\r
9b78c54a
HW
804 assert (TmpNode != NULL);\r
805\r
74bbe31b
DB
806 TmpNode->mNext = NewRestoreNodeBegin;\r
807 if (NewRestoreNodeEnd != NULL) {\r
808 NewRestoreNodeEnd->mNext = mBufferNodeQueueTail;\r
809 } else {\r
810 NewRestoreNodeBegin->mNext = mBufferNodeQueueTail;\r
811 }\r
4afd3d04
LG
812 }\r
813 }\r
74bbe31b 814 mCurrBufferNode = mBufferNodeQueueTail;\r
4afd3d04
LG
815 return VFR_RETURN_SUCCESS;\r
816}\r
817\r
30fdf114
LG
818EFI_VFR_RETURN_CODE\r
819CFormPkg::DeclarePendingQuestion (\r
820 IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB,\r
821 IN CVfrDataStorage &lCVfrDataStorage,\r
822 IN CVfrQuestionDB &lCVfrQuestionDB,\r
823 IN EFI_GUID *LocalFormSetGuid,\r
4afd3d04
LG
824 IN UINT32 LineNo,\r
825 OUT CHAR8 **InsertOpcodeAddr\r
30fdf114
LG
826 )\r
827{\r
828 SPendingAssign *pNode;\r
829 CHAR8 *VarStr;\r
830 UINT32 ArrayIdx;\r
831 CHAR8 FName[MAX_NAME_LEN];\r
b36d134f
LG
832 CHAR8 *SName;\r
833 CHAR8 *NewStr;\r
61eb9834 834 UINT32 ShrinkSize = 0;\r
30fdf114
LG
835 EFI_VFR_RETURN_CODE ReturnCode;\r
836 EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID;\r
42c808d4
DB
837 UINT8 LFlags;\r
838 UINT32 MaxValue;\r
839 CIfrGuid *GuidObj = NULL;\r
30fdf114 840\r
b36d134f
LG
841 //\r
842 // Declare all questions as Numeric in DisableIf True\r
843 //\r
844 // DisableIf\r
845 CIfrDisableIf DIObj;\r
846 DIObj.SetLineNo (LineNo);\r
5397bd42 847 *InsertOpcodeAddr = DIObj.GetObjBinAddr<CHAR8>();\r
b36d134f
LG
848 \r
849 //TrueOpcode\r
850 CIfrTrue TObj (LineNo);\r
851\r
852 // Declare Numeric qeustion for each undefined question.\r
30fdf114
LG
853 for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) {\r
854 if (pNode->mFlag == PENDING) {\r
30fdf114 855 EFI_VARSTORE_INFO Info; \r
4afd3d04 856 EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID;\r
30fdf114
LG
857 //\r
858 // Register this question, assume it is normal question, not date or time question\r
859 //\r
860 VarStr = pNode->mKey;\r
861 ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId);\r
862 if (ReturnCode != VFR_RETURN_SUCCESS) {\r
863 gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);\r
864 return ReturnCode;\r
865 }\r
866 \r
867#ifdef VFREXP_DEBUG\r
868 printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId);\r
869#endif\r
870 //\r
871 // Get Question Info, framework vfr VarName == StructName\r
872 //\r
873 ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx);\r
874 if (ReturnCode != VFR_RETURN_SUCCESS) {\r
875 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable");\r
876 return ReturnCode;\r
877 }\r
878 //\r
879 // Get VarStoreType\r
880 //\r
4afd3d04 881 ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId);\r
30fdf114
LG
882 if (ReturnCode != VFR_RETURN_SUCCESS) {\r
883 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined");\r
884 return ReturnCode;\r
885 }\r
4afd3d04 886 VarStoreType = lCVfrDataStorage.GetVarStoreType (Info.mVarStoreId); \r
30fdf114
LG
887\r
888 if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) {\r
889 ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx);\r
890 } else {\r
891 if (VarStoreType == EFI_VFR_VARSTORE_EFI) {\r
892 ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info);\r
42c808d4 893 } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_BUFFER_BITS) {\r
30fdf114 894 VarStr = pNode->mKey;\r
b36d134f 895 //convert VarStr with store name to VarStr with structure name\r
4afd3d04 896 ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (Info.mVarStoreId, &SName);\r
b36d134f
LG
897 if (ReturnCode == VFR_RETURN_SUCCESS) {\r
898 NewStr = new CHAR8[strlen (VarStr) + strlen (SName) + 1];\r
899 NewStr[0] = '\0';\r
900 strcpy (NewStr, SName);\r
901 strcat (NewStr, VarStr + strlen (FName));\r
42c808d4 902 ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize, Info.mIsBitVar);\r
fd542523 903 delete[] NewStr;\r
b36d134f 904 }\r
30fdf114
LG
905 } else {\r
906 ReturnCode = VFR_RETURN_UNSUPPORTED;\r
907 }\r
908 }\r
909 if (ReturnCode != VFR_RETURN_SUCCESS) {\r
910 gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey);\r
911 return ReturnCode;\r
912 }\r
0d2711a6 913 //\r
42c808d4 914 // If the storage is bit fields, create Guid opcode to wrap the numeric opcode.\r
0d2711a6 915 //\r
42c808d4
DB
916 if (Info.mIsBitVar) {\r
917 GuidObj = new CIfrGuid(0);\r
918 GuidObj->SetGuid (&gEdkiiIfrBitVarGuid);\r
919 GuidObj->SetLineNo(LineNo);\r
0d2711a6 920 }\r
42c808d4
DB
921\r
922 CIfrNumeric CNObj;\r
923 CNObj.SetLineNo (LineNo);\r
924 CNObj.SetPrompt (0x0);\r
925 CNObj.SetHelp (0x0);\r
926 CNObj.SetQuestionId (QId);\r
927 CNObj.SetVarStoreInfo (&Info);\r
928\r
2bcc713e 929 //\r
42c808d4 930 // Set Min/Max/Step Data and flags for the question with bit fields.Min/Max/Step Data are saved as UINT32 type for bit question.\r
2bcc713e 931 //\r
42c808d4
DB
932 if (Info.mIsBitVar) {\r
933 MaxValue = (1 << Info.mVarTotalSize) -1;\r
934 CNObj.SetMinMaxStepData ((UINT32) 0, MaxValue, (UINT32) 0);\r
4afd3d04 935 ShrinkSize = 12;\r
42c808d4
DB
936 LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & Info.mVarTotalSize);\r
937 CNObj.SetFlagsForBitField (0, LFlags);\r
938 } else {\r
939 //\r
940 // Numeric doesn't support BOOLEAN data type.\r
941 // BOOLEAN type has the same data size to UINT8.\r
942 //\r
943 if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) {\r
944 Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8;\r
945 }\r
946 CNObj.SetFlags (0, Info.mVarType);\r
947 //\r
948 // Use maximum value not to limit the vaild value for the undefined question.\r
949 //\r
950 switch (Info.mVarType) {\r
951 case EFI_IFR_TYPE_NUM_SIZE_64:\r
952 CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0);\r
953 ShrinkSize = 0;\r
954 break;\r
955 case EFI_IFR_TYPE_NUM_SIZE_32:\r
956 CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0);\r
957 ShrinkSize = 12;\r
958 break;\r
959 case EFI_IFR_TYPE_NUM_SIZE_16:\r
960 CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0);\r
961 ShrinkSize = 18;\r
962 break;\r
963 case EFI_IFR_TYPE_NUM_SIZE_8:\r
964 CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0);\r
965 ShrinkSize = 21;\r
966 break;\r
967 default:\r
968 break;\r
969 }\r
2bcc713e 970 }\r
4afd3d04 971 CNObj.ShrinkBinSize (ShrinkSize);\r
30fdf114
LG
972\r
973 //\r
974 // For undefined Efi VarStore type question\r
975 // Append the extended guided opcode to contain VarName\r
976 //\r
b36d134f 977 if (VarStoreType == EFI_VFR_VARSTORE_EFI || VfrCompatibleMode) {\r
30fdf114
LG
978 CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName);\r
979 CVNObj.SetLineNo (LineNo);\r
980 }\r
4afd3d04 981\r
30fdf114
LG
982 //\r
983 // End for Numeric\r
984 //\r
42c808d4 985 CIfrEnd CEObj;\r
30fdf114 986 CEObj.SetLineNo (LineNo);\r
42c808d4
DB
987 //\r
988 // End for Guided opcode\r
989 //\r
990 if (GuidObj != NULL) {\r
991 CIfrEnd CEObjGuid;\r
992 CEObjGuid.SetLineNo (LineNo);\r
993 GuidObj->SetScope(1);\r
994 delete GuidObj;\r
995 GuidObj = NULL;\r
996 }\r
30fdf114
LG
997 }\r
998 }\r
b36d134f
LG
999\r
1000 //\r
1001 // End for DisableIf\r
1002 //\r
1003 CIfrEnd SEObj;\r
1004 SEObj.SetLineNo (LineNo);\r
1005\r
30fdf114
LG
1006 return VFR_RETURN_SUCCESS;\r
1007}\r
1008\r
1009CFormPkg gCFormPkg;\r
1010\r
1011SIfrRecord::SIfrRecord (\r
1012 VOID\r
1013 )\r
1014{\r
1015 mIfrBinBuf = NULL;\r
1016 mBinBufLen = 0;\r
1017 mLineNo = 0xFFFFFFFF;\r
1018 mOffset = 0xFFFFFFFF;\r
1019 mNext = NULL;\r
1020}\r
1021\r
1022SIfrRecord::~SIfrRecord (\r
1023 VOID\r
1024 )\r
1025{\r
1026 if (mIfrBinBuf != NULL) {\r
1027 //delete mIfrBinBuf;\r
1028 mIfrBinBuf = NULL;\r
1029 }\r
1030 mLineNo = 0xFFFFFFFF;\r
1031 mOffset = 0xFFFFFFFF;\r
1032 mBinBufLen = 0;\r
1033 mNext = NULL;\r
1034}\r
1035\r
1036CIfrRecordInfoDB::CIfrRecordInfoDB (\r
1037 VOID\r
1038 )\r
1039{\r
1040 mSwitch = TRUE;\r
1041 mRecordCount = EFI_IFR_RECORDINFO_IDX_START;\r
1042 mIfrRecordListHead = NULL;\r
1043 mIfrRecordListTail = NULL;\r
74bbe31b
DB
1044 mAllDefaultTypeCount = 0;\r
1045 for (UINT8 i = 0; i < EFI_HII_MAX_SUPPORT_DEFAULT_TYPE; i++) {\r
1046 mAllDefaultIdArray[i] = 0xffff;\r
1047 }\r
30fdf114
LG
1048}\r
1049\r
1050CIfrRecordInfoDB::~CIfrRecordInfoDB (\r
1051 VOID\r
1052 )\r
1053{\r
1054 SIfrRecord *pNode;\r
1055\r
1056 while (mIfrRecordListHead != NULL) {\r
1057 pNode = mIfrRecordListHead;\r
1058 mIfrRecordListHead = mIfrRecordListHead->mNext;\r
1059 delete pNode;\r
1060 }\r
1061}\r
1062\r
1063SIfrRecord *\r
1064CIfrRecordInfoDB::GetRecordInfoFromIdx (\r
1065 IN UINT32 RecordIdx\r
1066 )\r
1067{\r
1068 UINT32 Idx;\r
1069 SIfrRecord *pNode = NULL;\r
1070\r
1071 if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) {\r
1072 return NULL;\r
1073 }\r
1074\r
1075 for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead;\r
1076 (Idx != RecordIdx) && (pNode != NULL);\r
1077 Idx++, pNode = pNode->mNext)\r
1078 ;\r
1079\r
1080 return pNode;\r
1081}\r
1082\r
1083UINT32\r
1084CIfrRecordInfoDB::IfrRecordRegister (\r
1085 IN UINT32 LineNo,\r
1086 IN CHAR8 *IfrBinBuf,\r
1087 IN UINT8 BinBufLen,\r
1088 IN UINT32 Offset\r
1089 )\r
1090{\r
1091 SIfrRecord *pNew;\r
1092\r
1093 if (mSwitch == FALSE) {\r
1094 return EFI_IFR_RECORDINFO_IDX_INVALUD;\r
1095 }\r
1096\r
1097 if ((pNew = new SIfrRecord) == NULL) {\r
1098 return EFI_IFR_RECORDINFO_IDX_INVALUD;\r
1099 }\r
1100\r
1101 if (mIfrRecordListHead == NULL) {\r
1102 mIfrRecordListHead = pNew;\r
1103 mIfrRecordListTail = pNew;\r
1104 } else {\r
1105 mIfrRecordListTail->mNext = pNew;\r
1106 mIfrRecordListTail = pNew;\r
1107 }\r
1108 mRecordCount++;\r
1109\r
1110 return mRecordCount;\r
1111}\r
1112\r
1113VOID\r
1114CIfrRecordInfoDB::IfrRecordInfoUpdate (\r
1115 IN UINT32 RecordIdx,\r
1116 IN UINT32 LineNo,\r
1117 IN CHAR8 *BinBuf,\r
1118 IN UINT8 BinBufLen,\r
1119 IN UINT32 Offset\r
1120 )\r
1121{\r
1122 SIfrRecord *pNode;\r
fd171542 1123 SIfrRecord *Prev;\r
30fdf114
LG
1124\r
1125 if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) {\r
1126 return;\r
1127 }\r
1128\r
fd171542 1129 if (LineNo == 0) {\r
1130 //\r
1131 // Line number is not specified explicitly, try to use line number of previous opcode\r
1132 //\r
1133 Prev = GetRecordInfoFromIdx (RecordIdx - 1);\r
1134 if (Prev != NULL) {\r
1135 LineNo = Prev->mLineNo;\r
1136 }\r
1137 }\r
1138\r
30fdf114
LG
1139 pNode->mLineNo = LineNo;\r
1140 pNode->mOffset = Offset;\r
1141 pNode->mBinBufLen = BinBufLen;\r
1142 pNode->mIfrBinBuf = BinBuf;\r
1143\r
1144}\r
1145\r
1146VOID\r
1147CIfrRecordInfoDB::IfrRecordOutput (\r
1148 OUT PACKAGE_DATA &TBuffer\r
1149 )\r
1150{\r
1151 CHAR8 *Temp;\r
1152 SIfrRecord *pNode; \r
1153\r
1154 if (TBuffer.Buffer != NULL) {\r
1155 delete TBuffer.Buffer;\r
1156 }\r
1157\r
1158 TBuffer.Size = 0;\r
1159 TBuffer.Buffer = NULL;\r
1160\r
1161\r
1162 if (mSwitch == FALSE) {\r
1163 return;\r
1164 } \r
1165 \r
1166 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {\r
1167 TBuffer.Size += pNode->mBinBufLen;\r
1168 }\r
1169 \r
1170 if (TBuffer.Size != 0) {\r
1171 TBuffer.Buffer = new CHAR8[TBuffer.Size];\r
1172 } else {\r
1173 return;\r
1174 }\r
1175 \r
1176 Temp = TBuffer.Buffer;\r
1177\r
1178 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {\r
1179 if (pNode->mIfrBinBuf != NULL) {\r
1180 memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen);\r
1181 Temp += pNode->mBinBufLen;\r
1182 }\r
1183 }\r
1184\r
1185 return; \r
1186} \r
1187\r
1188VOID\r
1189CIfrRecordInfoDB::IfrRecordOutput (\r
1190 IN FILE *File,\r
1191 IN UINT32 LineNo\r
1192 )\r
1193{\r
1194 SIfrRecord *pNode;\r
1195 UINT8 Index;\r
1196 UINT32 TotalSize;\r
1197\r
1198 if (mSwitch == FALSE) {\r
1199 return;\r
1200 }\r
1201\r
1202 if (File == NULL) {\r
1203 return;\r
1204 }\r
1205\r
1206 TotalSize = 0;\r
1207\r
1208 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {\r
1209 if (pNode->mLineNo == LineNo || LineNo == 0) {\r
1210 fprintf (File, ">%08X: ", pNode->mOffset);\r
1211 TotalSize += pNode->mBinBufLen;\r
1212 if (pNode->mIfrBinBuf != NULL) {\r
1213 for (Index = 0; Index < pNode->mBinBufLen; Index++) {\r
1214 fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index]));\r
1215 }\r
1216 }\r
1217 fprintf (File, "\n");\r
1218 }\r
1219 }\r
1220 \r
1221 if (LineNo == 0) {\r
1222 fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize);\r
1223 }\r
1224}\r
1225\r
1226//\r
1227// for framework vfr file\r
1228// adjust opcode sequence for uefi IFR format\r
1229// adjust inconsistent and varstore into the right position.\r
1230//\r
1231BOOLEAN\r
1232CIfrRecordInfoDB::CheckQuestionOpCode (\r
1233 IN UINT8 OpCode\r
1234 )\r
1235{\r
1236 switch (OpCode) {\r
1237 case EFI_IFR_CHECKBOX_OP:\r
1238 case EFI_IFR_NUMERIC_OP:\r
1239 case EFI_IFR_PASSWORD_OP:\r
1240 case EFI_IFR_ONE_OF_OP:\r
1241 case EFI_IFR_ACTION_OP:\r
1242 case EFI_IFR_STRING_OP:\r
1243 case EFI_IFR_DATE_OP:\r
1244 case EFI_IFR_TIME_OP:\r
1245 case EFI_IFR_ORDERED_LIST_OP:\r
bec3a181 1246 case EFI_IFR_REF_OP:\r
30fdf114
LG
1247 return TRUE;\r
1248 default:\r
1249 return FALSE;\r
1250 }\r
1251}\r
1252\r
1253BOOLEAN\r
1254CIfrRecordInfoDB::CheckIdOpCode (\r
1255 IN UINT8 OpCode\r
1256 )\r
1257{\r
1258 switch (OpCode) {\r
1259 case EFI_IFR_EQ_ID_VAL_OP:\r
1260 case EFI_IFR_EQ_ID_ID_OP:\r
64b2609f 1261 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
30fdf114
LG
1262 case EFI_IFR_QUESTION_REF1_OP:\r
1263 return TRUE;\r
1264 default:\r
1265 return FALSE;\r
1266 }\r
1267} \r
1268\r
1269EFI_QUESTION_ID\r
1270CIfrRecordInfoDB::GetOpcodeQuestionId (\r
1271 IN EFI_IFR_OP_HEADER *OpHead\r
1272 )\r
1273{\r
1274 EFI_IFR_QUESTION_HEADER *QuestionHead;\r
1275 \r
1276 QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1);\r
1277 \r
1278 return QuestionHead->QuestionId;\r
1279}\r
1280\r
4afd3d04
LG
1281SIfrRecord *\r
1282CIfrRecordInfoDB::GetRecordInfoFromOffset (\r
1283 IN UINT32 Offset\r
1284 )\r
1285{\r
1286 SIfrRecord *pNode = NULL;\r
1287\r
1288 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {\r
1289 if (pNode->mOffset == Offset) {\r
1290 return pNode;\r
1291 }\r
1292 }\r
1293\r
1294 return pNode;\r
1295}\r
1296\r
74bbe31b 1297/**\r
4afd3d04
LG
1298 Add just the op code position.\r
1299\r
74bbe31b
DB
1300 Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode,\r
1301 so pDynamicOpcodeNodes is before mIfrRecordListTail.\r
1302\r
4afd3d04 1303 From\r
74bbe31b
DB
1304\r
1305 |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail|\r
1306\r
4afd3d04 1307 To\r
4afd3d04 1308\r
74bbe31b
DB
1309 |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail|\r
1310\r
1311 Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file,\r
1312 so new records are appennded to the end of OriginalIfrRecordListTail.\r
1313\r
1314 From\r
1315\r
1316 |mIfrRecordListHead + ...+ pAdjustNode + ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes|\r
1317\r
1318 To\r
1319\r
1320 |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + ... + OriginalIfrRecordListTail|\r
1321\r
1322\r
1323 @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file.\r
1324\r
1325**/\r
4afd3d04
LG
1326BOOLEAN\r
1327CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords (\r
74bbe31b 1328 IN BOOLEAN CreateOpcodeAfterParsingVfr\r
4afd3d04
LG
1329 )\r
1330{\r
1331 UINT32 OpcodeOffset;\r
1332 SIfrRecord *pNode, *pPreNode;\r
74bbe31b
DB
1333 SIfrRecord *pAdjustNode, *pNodeBeforeAdjust;\r
1334 SIfrRecord *pNodeBeforeDynamic;\r
1335\r
61eb9834 1336 pPreNode = NULL;\r
74bbe31b
DB
1337 pAdjustNode = NULL;\r
1338 pNodeBeforeDynamic = NULL;\r
1339 OpcodeOffset = 0;\r
4afd3d04
LG
1340\r
1341 //\r
74bbe31b
DB
1342 // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode,\r
1343 // and the node before pDynamicOpcodeNode.\r
4afd3d04 1344 //\r
74bbe31b 1345 for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) {\r
4afd3d04 1346 if (OpcodeOffset == gAdjustOpcodeOffset) {\r
74bbe31b
DB
1347 pAdjustNode = pNode;\r
1348 pNodeBeforeAdjust = pPreNode;\r
4afd3d04 1349 } else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) {\r
74bbe31b
DB
1350 pNodeBeforeDynamic = pPreNode;\r
1351 }\r
1352 if (pNode->mNext != NULL) {\r
1353 pPreNode = pNode;\r
4afd3d04 1354 }\r
4afd3d04
LG
1355 OpcodeOffset += pNode->mBinBufLen;\r
1356 }\r
1357\r
1358 //\r
74bbe31b 1359 // Check the nodes whether exist.\r
4afd3d04 1360 //\r
9b78c54a 1361 if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL || pNodeBeforeAdjust == NULL) {\r
4afd3d04
LG
1362 return FALSE;\r
1363 }\r
1364\r
1365 //\r
1366 // Adjust the node. pPreNode save the Node before mIfrRecordListTail\r
1367 //\r
74bbe31b
DB
1368 pNodeBeforeAdjust->mNext = pNodeBeforeDynamic->mNext;\r
1369 if (CreateOpcodeAfterParsingVfr) {\r
1370 //\r
1371 // mIfrRecordListTail is the end of pDynamicNode (Case2).\r
1372 //\r
1373 mIfrRecordListTail->mNext = pAdjustNode;\r
1374 mIfrRecordListTail = pNodeBeforeDynamic;\r
1375 mIfrRecordListTail->mNext = NULL;\r
1376 } else {\r
1377 //\r
1378 //pPreNode is the end of pDynamicNode(Case1).\r
1379 //\r
1380 pPreNode->mNext = pAdjustNode;\r
1381 pNodeBeforeDynamic->mNext = mIfrRecordListTail;\r
1382 }\r
4afd3d04
LG
1383\r
1384 return TRUE;\r
1385}\r
1386\r
74bbe31b
DB
1387/**\r
1388 Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record.\r
1389\r
1390 @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file.\r
1391\r
1392**/\r
1393VOID\r
1394CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode (\r
1395 IN BOOLEAN CreateOpcodeAfterParsingVfr\r
1396 )\r
1397{\r
1398 SIfrRecord *pRecord;\r
1399\r
1400 //\r
1401 // Base on the original offset info to update the record list.\r
1402 //\r
1403 if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr)) {\r
00de920a 1404 gCVfrErrorHandle.PrintMsg (0, (CHAR8 *)"Error", (CHAR8 *)"Can not find the adjust offset in the record.");\r
74bbe31b
DB
1405 }\r
1406\r
1407 //\r
1408 // Base on the opcode binary length to recalculate the offset for each opcode.\r
1409 //\r
1410 IfrAdjustOffsetForRecord();\r
1411\r
1412 //\r
1413 // Base on the offset to find the binary address.\r
1414 //\r
1415 pRecord = GetRecordInfoFromOffset(gAdjustOpcodeOffset);\r
1416 while (pRecord != NULL) {\r
1417 pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset);\r
1418 pRecord = pRecord->mNext;\r
1419 }\r
1420}\r
1421\r
1422\r
4afd3d04
LG
1423VOID\r
1424CIfrRecordInfoDB::IfrAdjustOffsetForRecord (\r
1425 VOID\r
1426 )\r
1427{\r
1428 UINT32 OpcodeOffset;\r
1429 SIfrRecord *pNode;\r
1430\r
1431 OpcodeOffset = 0;\r
1432 for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) {\r
1433 pNode->mOffset = OpcodeOffset;\r
1434 OpcodeOffset += pNode->mBinBufLen;\r
1435 }\r
1436}\r
1437\r
30fdf114
LG
1438EFI_VFR_RETURN_CODE\r
1439CIfrRecordInfoDB::IfrRecordAdjust (\r
1440 VOID\r
1441 )\r
1442{\r
1443 SIfrRecord *pNode, *preNode;\r
1444 SIfrRecord *uNode, *tNode;\r
1445 EFI_IFR_OP_HEADER *OpHead, *tOpHead;\r
1446 EFI_QUESTION_ID QuestionId;\r
1447 UINT32 StackCount;\r
1448 UINT32 QuestionScope;\r
30fdf114
LG
1449 CHAR8 ErrorMsg[MAX_STRING_LEN] = {0, };\r
1450 EFI_VFR_RETURN_CODE Status;\r
1451\r
1452 //\r
1453 // Init local variable\r
1454 //\r
1455 Status = VFR_RETURN_SUCCESS;\r
1456 pNode = mIfrRecordListHead;\r
1457 preNode = pNode;\r
1458 QuestionScope = 0;\r
1459 while (pNode != NULL) {\r
1460 OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;\r
1461 \r
1462 //\r
1463 // make sure the inconsistent opcode in question scope\r
1464 //\r
1465 if (QuestionScope > 0) {\r
1466 QuestionScope += OpHead->Scope;\r
1467 if (OpHead->OpCode == EFI_IFR_END_OP) {\r
1468 QuestionScope --;\r
1469 }\r
1470 }\r
1471 \r
1472 if (CheckQuestionOpCode (OpHead->OpCode)) {\r
1473 QuestionScope = 1;\r
1474 }\r
1475 //\r
1476 // for the inconsistent opcode not in question scope, adjust it\r
1477 //\r
1478 if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) {\r
1479 //\r
1480 // for inconsistent opcode not in question scope\r
1481 //\r
1482\r
1483 //\r
1484 // Count inconsistent opcode Scope \r
1485 //\r
1486 StackCount = OpHead->Scope;\r
1487 QuestionId = EFI_QUESTION_ID_INVALID;\r
1488 tNode = pNode;\r
1489 while (tNode != NULL && StackCount > 0) {\r
1490 tNode = tNode->mNext;\r
1491 tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf;\r
1492 //\r
1493 // Calculate Scope Number\r
1494 //\r
1495 StackCount += tOpHead->Scope;\r
1496 if (tOpHead->OpCode == EFI_IFR_END_OP) {\r
1497 StackCount --;\r
1498 }\r
1499 //\r
1500 // by IdEqual opcode to get QuestionId\r
1501 //\r
1502 if (QuestionId == EFI_QUESTION_ID_INVALID && \r
1503 CheckIdOpCode (tOpHead->OpCode)) {\r
1504 QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1);\r
1505 }\r
1506 }\r
1507 if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) {\r
1508 //\r
1509 // report error; not found\r
1510 //\r
1511 sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId);\r
1512 gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);\r
1513 Status = VFR_RETURN_MISMATCHED;\r
1514 break;\r
1515 }\r
1516 //\r
1517 // extract inconsistent opcode list\r
1518 // pNode is Incosistent opcode, tNode is End Opcode\r
1519 //\r
1520 \r
1521 //\r
1522 // insert inconsistent opcode list into the right question scope by questionid\r
1523 //\r
1524 for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) {\r
1525 tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf;\r
1526 if (CheckQuestionOpCode (tOpHead->OpCode) && \r
1527 (QuestionId == GetOpcodeQuestionId (tOpHead))) {\r
1528 break;\r
1529 }\r
1530 }\r
1531 //\r
1532 // insert inconsistent opcode list and check LATE_CHECK flag\r
1533 //\r
1534 if (uNode != NULL) {\r
1535 if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) {\r
1536 //\r
1537 // if LATE_CHECK flag is set, change inconsistent to nosumbit\r
1538 //\r
1539 OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP;\r
1540 }\r
1541 \r
1542 //\r
1543 // skip the default storage for Date and Time\r
1544 //\r
1545 if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) {\r
1546 uNode = uNode->mNext;\r
1547 }\r
1548\r
1549 preNode->mNext = tNode->mNext;\r
1550 tNode->mNext = uNode->mNext;\r
1551 uNode->mNext = pNode;\r
1552 //\r
1553 // reset pNode to head list, scan the whole list again.\r
1554 //\r
1555 pNode = mIfrRecordListHead;\r
1556 preNode = pNode;\r
1557 QuestionScope = 0;\r
1558 continue;\r
1559 } else {\r
1560 //\r
1561 // not found matched question id, report error\r
1562 //\r
1563 sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId);\r
1564 gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg);\r
1565 Status = VFR_RETURN_MISMATCHED;\r
1566 break;\r
1567 }\r
1568 } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP || \r
1569 OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) {\r
1570 //\r
1571 // for new added group of varstore opcode\r
1572 //\r
1573 tNode = pNode;\r
1574 while (tNode->mNext != NULL) {\r
1575 tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf;\r
1576 if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP && \r
1577 tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) {\r
1578 break; \r
1579 }\r
1580 tNode = tNode->mNext;\r
1581 }\r
1582\r
1583 if (tNode->mNext == NULL) {\r
1584 //\r
1585 // invalid IfrCode, IfrCode end by EndOpCode\r
1586 // \r
1587 gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end");\r
1588 Status = VFR_RETURN_MISMATCHED;\r
1589 break;\r
1590 }\r
1591 \r
1592 if (tOpHead->OpCode != EFI_IFR_END_OP) {\r
1593 //\r
1594 // not new added varstore, which are not needed to be adjust.\r
1595 //\r
1596 preNode = tNode;\r
1597 pNode = tNode->mNext;\r
1598 continue; \r
1599 } else {\r
1600 //\r
1601 // move new added varstore opcode to the position befor form opcode \r
1602 // varstore opcode between pNode and tNode\r
1603 //\r
1604\r
1605 //\r
1606 // search form opcode from begin\r
1607 //\r
1608 for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) {\r
1609 tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf;\r
1610 if (tOpHead->OpCode == EFI_IFR_FORM_OP) {\r
1611 break;\r
1612 }\r
1613 }\r
1614 //\r
1615 // Insert varstore opcode beform form opcode if form opcode is found\r
1616 //\r
1617 if (uNode->mNext != NULL) {\r
1618 preNode->mNext = tNode->mNext;\r
1619 tNode->mNext = uNode->mNext;\r
1620 uNode->mNext = pNode;\r
1621 //\r
1622 // reset pNode to head list, scan the whole list again.\r
1623 //\r
1624 pNode = mIfrRecordListHead;\r
1625 preNode = pNode;\r
1626 QuestionScope = 0;\r
1627 continue;\r
1628 } else {\r
1629 //\r
1630 // not found form, continue scan IfrRecord list\r
1631 //\r
1632 preNode = tNode;\r
1633 pNode = tNode->mNext;\r
1634 continue;\r
1635 }\r
1636 }\r
1637 }\r
1638 //\r
1639 // next node\r
1640 //\r
1641 preNode = pNode;\r
1642 pNode = pNode->mNext; \r
1643 }\r
1644 \r
1645 //\r
1646 // Update Ifr Opcode Offset\r
1647 //\r
1648 if (Status == VFR_RETURN_SUCCESS) {\r
4afd3d04 1649 IfrAdjustOffsetForRecord ();\r
30fdf114
LG
1650 }\r
1651 return Status;\r
1652}\r
1653\r
74bbe31b
DB
1654/**\r
1655 When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not\r
1656 given by expression, should save the default info for the Buffer VarStore.\r
1657\r
1658 @param DefaultId The default id.\r
1659 @param pQuestionNode Point to the question opcode node.\r
1660 @param Value The default value.\r
1661**/\r
1662VOID\r
1663CIfrRecordInfoDB::IfrAddDefaultToBufferConfig (\r
1664 IN UINT16 DefaultId,\r
1665 IN SIfrRecord *pQuestionNode,\r
1666 IN EFI_IFR_TYPE_VALUE Value\r
1667 )\r
1668{\r
1669 CHAR8 *VarStoreName = NULL;\r
1670 EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID;\r
1671 EFI_GUID *VarGuid = NULL;\r
1672 EFI_VARSTORE_INFO VarInfo;\r
1673 EFI_IFR_QUESTION_HEADER *QuestionHead;\r
1674 EFI_IFR_OP_HEADER *pQuestionOpHead;\r
1675\r
1676 pQuestionOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;\r
1677 QuestionHead = (EFI_IFR_QUESTION_HEADER *) (pQuestionOpHead + 1);\r
1678\r
1679 //\r
1680 // Get the Var Store name and type.\r
1681 //\r
1682 gCVfrDataStorage.GetVarStoreName (QuestionHead->VarStoreId, &VarStoreName);\r
1683 VarGuid= gCVfrDataStorage.GetVarStoreGuid (QuestionHead->VarStoreId);\r
1684 VarStoreType = gCVfrDataStorage.GetVarStoreType (QuestionHead->VarStoreId);\r
1685\r
1686 //\r
1687 // Only for Buffer storage need to save the default info in the storage.\r
1688 // Other type storage, just return.\r
1689 //\r
1690 if (VarStoreType != EFI_VFR_VARSTORE_BUFFER) {\r
1691 return;\r
1692 } else {\r
1693 VarInfo.mInfo.mVarOffset = QuestionHead->VarStoreInfo.VarOffset;\r
1694 VarInfo.mVarStoreId = QuestionHead->VarStoreId;\r
1695 }\r
1696\r
1697 //\r
1698 // Get the buffer storage info about this question.\r
1699 //\r
1700 gCVfrDataStorage.GetBufferVarStoreFieldInfo (&VarInfo);\r
1701\r
1702 //\r
1703 // Add action.\r
1704 //\r
1705 gCVfrDefaultStore.BufferVarStoreAltConfigAdd (\r
1706 DefaultId,\r
1707 VarInfo,\r
1708 VarStoreName,\r
1709 VarGuid,\r
1710 VarInfo.mVarType,\r
1711 Value\r
1712 );\r
1713}\r
1714\r
1715/**\r
1716 Record the number and default id of all defaultstore opcode.\r
1717\r
1718**/\r
1719VOID\r
1720CIfrRecordInfoDB::IfrGetDefaultStoreInfo (\r
1721 VOID\r
1722 )\r
1723{\r
1724 SIfrRecord *pNode;\r
1725 EFI_IFR_OP_HEADER *pOpHead;\r
1726 EFI_IFR_DEFAULTSTORE *DefaultStore;\r
1727\r
1728 pNode = mIfrRecordListHead;\r
1729 mAllDefaultTypeCount = 0;\r
1730\r
1731 while (pNode != NULL) {\r
1732 pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;\r
1733\r
1734 if (pOpHead->OpCode == EFI_IFR_DEFAULTSTORE_OP){\r
1735 DefaultStore = (EFI_IFR_DEFAULTSTORE *) pNode->mIfrBinBuf;\r
1736 mAllDefaultIdArray[mAllDefaultTypeCount++] = DefaultStore->DefaultId;\r
1737 }\r
1738 pNode = pNode->mNext;\r
1739 }\r
1740}\r
1741\r
1742/**\r
1743 Create new default opcode record.\r
1744\r
1745 @param Size The new default opcode size.\r
1746 @param DefaultId The new default id.\r
1747 @param Type The new default type.\r
1748 @param LineNo The line number of the new record.\r
1749 @param Value The new default value.\r
1750\r
1751**/\r
1752VOID\r
1753CIfrRecordInfoDB::IfrCreateDefaultRecord(\r
1754 IN UINT8 Size,\r
1755 IN UINT16 DefaultId,\r
1756 IN UINT8 Type,\r
1757 IN UINT32 LineNo,\r
1758 IN EFI_IFR_TYPE_VALUE Value\r
1759 )\r
1760{\r
1761 CIfrDefault *DObj;\r
1762 CIfrDefault2 *DObj2;\r
1763\r
1764 DObj = NULL;\r
1765 DObj2 = NULL;\r
1766\r
1767 if (Type == EFI_IFR_TYPE_OTHER) {\r
1768 DObj2 = new CIfrDefault2 (Size);\r
1769 DObj2->SetDefaultId(DefaultId);\r
1770 DObj2->SetType(Type);\r
1771 DObj2->SetLineNo(LineNo);\r
1772 DObj2->SetScope (1);\r
1773 delete DObj2;\r
1774 } else {\r
1775 DObj = new CIfrDefault (Size);\r
1776 DObj->SetDefaultId(DefaultId);\r
1777 DObj->SetType(Type);\r
1778 DObj->SetLineNo(LineNo);\r
1779 DObj->SetValue (Value);\r
1780 delete DObj;\r
1781 }\r
1782}\r
1783\r
1784/**\r
1785 Create new default opcode for question base on the QuestionDefaultInfo.\r
1786\r
1787 @param pQuestionNode Point to the question opcode Node.\r
1788 @param QuestionDefaultInfo Point to the QuestionDefaultInfo for current question.\r
1789\r
1790**/\r
1791VOID\r
1792CIfrRecordInfoDB::IfrCreateDefaultForQuestion (\r
1793 IN SIfrRecord *pQuestionNode,\r
1794 IN QuestionDefaultRecord *QuestionDefaultInfo\r
1795 )\r
1796{\r
1797 EFI_IFR_OP_HEADER *pOpHead;\r
1798 EFI_IFR_DEFAULT *Default;\r
1799 SIfrRecord *pSNode;\r
1800 SIfrRecord *pENode;\r
1801 SIfrRecord *pDefaultNode;\r
1802 CIfrObj *Obj;\r
1803 CHAR8 *ObjBinBuf;\r
1804 UINT8 ScopeCount;\r
1805 UINT8 OpcodeNumber;\r
1806 UINT8 OpcodeCount;\r
1807 UINT8 DefaultSize;\r
1808 EFI_IFR_ONE_OF_OPTION *DefaultOptionOpcode;\r
1809 EFI_IFR_TYPE_VALUE CheckBoxDefaultValue;\r
1810\r
1811 CheckBoxDefaultValue.b = 1;\r
1812 pOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf;\r
1813 ScopeCount = 0;\r
1814 OpcodeCount = 0;\r
1815 Obj = NULL;\r
1816\r
1817 //\r
1818 // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.\r
1819 //\r
1820 gAdjustOpcodeOffset = pQuestionNode->mNext->mOffset;\r
1821 //\r
1822 // Case 1:\r
1823 // For oneof, the default with smallest default id is given by the option flag.\r
1824 // So create the missing defaults base on the oneof option value(mDefaultValueRecord).\r
1825 //\r
1826 if (pOpHead->OpCode == EFI_IFR_ONE_OF_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {\r
1827 DefaultOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)QuestionDefaultInfo->mDefaultValueRecord->mIfrBinBuf;\r
1828 DefaultSize = QuestionDefaultInfo->mDefaultValueRecord->mBinBufLen - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value);\r
1829 DefaultSize += OFFSET_OF (EFI_IFR_DEFAULT, Value);\r
1830 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
1831 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
1832 IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], DefaultOptionOpcode->Type, pQuestionNode->mLineNo, DefaultOptionOpcode->Value);\r
1833 //\r
1834 // Save the new created default in the buffer storage.\r
1835 //\r
1836 IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, DefaultOptionOpcode->Value);\r
1837 }\r
1838 }\r
1839 return;\r
1840 }\r
1841\r
1842 //\r
1843 // Case2:\r
1844 // For checkbox, the default with smallest default id is given by the question flag.\r
1845 // And create the missing defaults with true value.\r
1846 //\r
1847 if (pOpHead-> OpCode == EFI_IFR_CHECKBOX_OP && !QuestionDefaultInfo->mIsDefaultOpcode) {\r
1848 DefaultSize = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (BOOLEAN);\r
1849 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
1850 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
1851 IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], EFI_IFR_TYPE_BOOLEAN, pQuestionNode->mLineNo, CheckBoxDefaultValue);\r
1852 //\r
1853 // Save the new created default.\r
1854 //\r
1855 IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, CheckBoxDefaultValue);\r
1856 }\r
1857 }\r
1858 return;\r
1859 }\r
1860\r
1861 //\r
1862 // Case3:\r
1863 // The default with smallest default id is given by the default opcode.\r
1864 // So create the missing defaults base on the value in the default opcode.\r
1865 //\r
1866\r
1867 //\r
1868 // pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo.\r
1869 //\r
1870 pDefaultNode = QuestionDefaultInfo->mDefaultValueRecord;\r
1871 Default = (EFI_IFR_DEFAULT *)pDefaultNode->mIfrBinBuf;\r
1872 //\r
1873 // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.\r
1874 //\r
1875 gAdjustOpcodeOffset = pDefaultNode->mNext->mOffset;\r
1876\r
1877 if (Default->Type == EFI_IFR_TYPE_OTHER) {\r
1878 //\r
1879 // EFI_IFR_DEFAULT_2 opcode.\r
1880 //\r
1881 // Point to the first expression opcode.\r
1882 //\r
1883 pSNode = pDefaultNode->mNext;\r
61eb9834 1884 pENode = NULL;\r
74bbe31b
DB
1885 ScopeCount++;\r
1886 //\r
1887 // Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2)\r
1888 //\r
1889 while (pSNode != NULL && pSNode->mNext != NULL && ScopeCount != 0) {\r
1890 pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;\r
1891 if (pOpHead->Scope == 1) {\r
1892 ScopeCount++;\r
1893 }\r
1894 if (pOpHead->OpCode == EFI_IFR_END_OP) {\r
1895 ScopeCount--;\r
1896 }\r
1897 pENode = pSNode;\r
1898 pSNode = pSNode->mNext;\r
1899 OpcodeCount++;\r
1900 }\r
9b78c54a
HW
1901\r
1902 assert (pSNode);\r
1903 assert (pENode);\r
1904\r
74bbe31b
DB
1905 //\r
1906 // Record the offset of node which need to be adjust, will move the new created default opcode to this offset.\r
1907 //\r
1908 gAdjustOpcodeOffset = pSNode->mOffset;\r
1909 //\r
1910 // Create new default opcode node for missing default.\r
1911 //\r
1912 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
1913 OpcodeNumber = OpcodeCount;\r
1914 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
1915 IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pENode->mLineNo, Default->Value);\r
1916 //\r
1917 // Point to the first expression opcode node.\r
1918 //\r
1919 pSNode = pDefaultNode->mNext;\r
1920 //\r
1921 // Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode.\r
1922 //\r
1923 while (pSNode != NULL && pSNode->mNext != NULL && OpcodeNumber-- != 0) {\r
1924 pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;\r
1925 Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE);\r
9b78c54a 1926 assert (Obj != NULL);\r
74bbe31b 1927 Obj->SetLineNo (pSNode->mLineNo);\r
5397bd42 1928 ObjBinBuf = Obj->GetObjBinAddr<CHAR8>();\r
74bbe31b
DB
1929 memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen);\r
1930 delete Obj;\r
1931 pSNode = pSNode->mNext;\r
1932 }\r
1933 }\r
1934 }\r
1935 } else {\r
1936 //\r
1937 // EFI_IFR_DEFAULT opcode.\r
1938 //\r
1939 // Create new default opcode node for missing default.\r
1940 //\r
1941 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
1942 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
1943 IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pDefaultNode->mLineNo, Default->Value);\r
1944 //\r
1945 // Save the new created default in the buffer storage..\r
1946 //\r
1947 IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, Default->Value);\r
1948 }\r
1949 }\r
1950 }\r
1951}\r
1952\r
1953/**\r
1954 Parse the default information in a question, get the QuestionDefaultInfo.\r
1955\r
1956 @param pQuestionNode Point to the question record Node.\r
1957 @param QuestionDefaultInfo On return, point to the QuestionDefaultInfo.\r
1958**/\r
1959VOID\r
1960CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion(\r
1961 IN SIfrRecord *pQuestionNode,\r
1962 OUT QuestionDefaultRecord *QuestionDefaultInfo\r
1963 )\r
1964{\r
1965 SIfrRecord *pSNode;\r
1966 EFI_IFR_ONE_OF_OPTION *OneofOptionOpcode;\r
1967 EFI_IFR_OP_HEADER *pSOpHead;\r
1968 EFI_IFR_CHECKBOX *CheckBoxOpcode;\r
1969 EFI_IFR_DEFAULT *DefaultOpcode;\r
1970 BOOLEAN IsOneOfOpcode;\r
1971 UINT16 SmallestDefaultId;\r
1972 UINT8 ScopeCount;\r
1973\r
1974 SmallestDefaultId = 0xffff;\r
1975 IsOneOfOpcode = FALSE;\r
1976 ScopeCount = 0;\r
1977 pSNode = pQuestionNode;\r
1978\r
1979 //\r
1980 // Parse all the opcodes in the Question.\r
1981 //\r
1982 while (pSNode != NULL) {\r
1983 pSOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf;\r
1984 //\r
1985 // For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP.\r
1986 // Scopes may be nested within other scopes.\r
1987 // When finishing parsing a question, the scope count must be zero.\r
1988 //\r
1989 if (pSOpHead->Scope == 1) {\r
1990 ScopeCount++;\r
1991 }\r
1992 if (pSOpHead->OpCode == EFI_IFR_END_OP) {\r
1993 ScopeCount--;\r
1994 }\r
1995 //\r
1996 // Check whether finishing parsing a question.\r
1997 //\r
1998 if (ScopeCount == 0) {\r
1999 break;\r
2000 }\r
2001\r
2002 //\r
2003 // Record the default information in the question.\r
2004 //\r
2005 switch (pSOpHead->OpCode) {\r
2006 case EFI_IFR_ONE_OF_OP:\r
2007 IsOneOfOpcode = TRUE;\r
2008 break;\r
2009 case EFI_IFR_CHECKBOX_OP:\r
2010 //\r
2011 // The default info of check box may be given by flag.\r
2012 // So need to check the flag of check box.\r
2013 //\r
2014 CheckBoxOpcode = (EFI_IFR_CHECKBOX *)pSNode->mIfrBinBuf;\r
2015 if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0) {\r
2016 //\r
2017 // Check whether need to update the smallest default id.\r
2018 //\r
2019 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2020 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2021 }\r
2022 //\r
2023 // Update the QuestionDefaultInfo.\r
2024 //\r
2025 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
2026 if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2027 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
2028 QuestionDefaultInfo->mDefaultNumber ++;\r
2029 QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
2030 }\r
2031 break;\r
2032 }\r
2033 }\r
2034 }\r
2035 if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0) {\r
2036 //\r
2037 // Check whether need to update the smallest default id.\r
2038 //\r
2039 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2040 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2041 }\r
2042 //\r
2043 // Update the QuestionDefaultInfo.\r
2044 //\r
2045 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
2046 if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2047 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
2048 QuestionDefaultInfo->mDefaultNumber ++;\r
2049 QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
2050 }\r
2051 break;\r
2052 }\r
2053 }\r
2054 }\r
2055 break;\r
2056 case EFI_IFR_ONE_OF_OPTION_OP:\r
2057 if (!IsOneOfOpcode) {\r
2058 //\r
2059 // Only check the option in oneof.\r
2060 //\r
2061 break;\r
2062 }\r
2063 OneofOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)pSNode->mIfrBinBuf;\r
2064 if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {\r
2065 //\r
2066 // The option is used as the standard default.\r
2067 // Check whether need to update the smallest default id and QuestionDefaultInfo.\r
2068 //\r
2069 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2070 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
2071 QuestionDefaultInfo->mDefaultValueRecord = pSNode;\r
2072 }\r
2073 //\r
2074 // Update the IsDefaultIdExist array in QuestionDefaultInfo.\r
2075 //\r
2076 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
2077 if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
2078 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
2079 QuestionDefaultInfo->mDefaultNumber ++;\r
2080 QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
2081 }\r
2082 break;\r
2083 }\r
2084 }\r
2085 }\r
2086 if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0) {\r
2087 //\r
2088 // This option is used as the manufacture default.\r
2089 // Check whether need to update the smallest default id and QuestionDefaultInfo.\r
2090 //\r
2091 if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2092 SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
2093 QuestionDefaultInfo->mDefaultValueRecord = pSNode;\r
2094 }\r
2095 //\r
2096 // Update the QuestionDefaultInfo.\r
2097 //\r
2098 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) {\r
2099 if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
2100 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
2101 QuestionDefaultInfo->mDefaultNumber ++;\r
2102 QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
2103 }\r
2104 break;\r
2105 }\r
2106 }\r
2107 }\r
2108 break;\r
2109 case EFI_IFR_DEFAULT_OP:\r
2110 DefaultOpcode = (EFI_IFR_DEFAULT *) pSNode->mIfrBinBuf;\r
2111 //\r
2112 // Check whether need to update the smallest default id and QuestionDefaultInfo.\r
2113 //\r
2114 if (SmallestDefaultId >= DefaultOpcode->DefaultId ) {\r
2115 SmallestDefaultId = DefaultOpcode->DefaultId;\r
2116 QuestionDefaultInfo->mDefaultValueRecord= pSNode;\r
2117 QuestionDefaultInfo->mIsDefaultOpcode= TRUE;\r
2118 }\r
2119 //\r
2120 // Update the QuestionDefaultInfo.\r
2121 //\r
2122 for (UINT8 i = 0; i < mAllDefaultTypeCount; i++){\r
2123 if (mAllDefaultIdArray[i] == ((EFI_IFR_DEFAULT *)pSNode->mIfrBinBuf)->DefaultId) {\r
2124 if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) {\r
2125 QuestionDefaultInfo->mDefaultNumber ++;\r
2126 QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE;\r
2127 }\r
2128 break;\r
2129 }\r
2130 }\r
2131 break;\r
2132 default:\r
2133 break;\r
2134 }\r
2135 //\r
2136 // Parse next opcode in this question.\r
2137 //\r
2138 pSNode = pSNode->mNext;\r
2139 }\r
2140}\r
2141\r
2142/**\r
2143 Check or add default for question if need.\r
2144\r
2145 This function will check the default info for question.\r
2146 If the question has default, but the default number < defaultstore opcode number.\r
2147 will do following two action :\r
2148\r
2149 1. if (AutoDefault) will add default for question to support all kinds of defaults.\r
2150 2. if (CheckDefault) will generate an error to tell user the question misses some default value.\r
2151\r
2152 We assume that the two options can not be TRUE at same time.\r
2153 If they are TRUE at same time, only do the action corresponding to AutoDefault option.\r
2154\r
2155 @param AutoDefault Add default for question if needed\r
2156 @param CheckDefault Check the default info, if missing default, generates an error.\r
2157\r
2158**/\r
2159VOID\r
2160CIfrRecordInfoDB::IfrCheckAddDefaultRecord (\r
2161 BOOLEAN AutoDefault,\r
2162 BOOLEAN CheckDefault\r
2163 )\r
2164{\r
2165 SIfrRecord *pNode;\r
2166 SIfrRecord *pTailNode;\r
2167 SIfrRecord *pStartAdjustNode;\r
2168 EFI_IFR_OP_HEADER *pOpHead;\r
2169 QuestionDefaultRecord QuestionDefaultInfo;\r
2170 UINT8 MissingDefaultCount;\r
2171 CHAR8 Msg[MAX_STRING_LEN] = {0, };\r
2172\r
2173 pNode = mIfrRecordListHead;\r
2174\r
2175 //\r
2176 // Record the number and default id of all defaultstore opcode.\r
2177 //\r
2178 IfrGetDefaultStoreInfo ();\r
2179\r
2180 while (pNode != NULL) {\r
2181 pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf;\r
2182 //\r
2183 // Check whether is question opcode.\r
2184 //\r
2185 if (CheckQuestionOpCode (pOpHead->OpCode)) {\r
2186 //\r
2187 // Initialize some local variables here, because they vary with question.\r
2188 // Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail.\r
2189 //\r
2190 memset (&QuestionDefaultInfo, 0, sizeof (QuestionDefaultRecord));\r
2191 pTailNode = mIfrRecordListTail;\r
2192 //\r
2193 // Get the QuestionDefaultInfo for current question.\r
2194 //\r
2195 IfrParseDefaulInfoInQuestion (pNode, &QuestionDefaultInfo);\r
2196\r
2197 if (QuestionDefaultInfo.mDefaultNumber != mAllDefaultTypeCount && QuestionDefaultInfo.mDefaultNumber != 0) {\r
2198 if (AutoDefault) {\r
2199 //\r
2200 // Create default for question which misses default.\r
2201 //\r
2202 IfrCreateDefaultForQuestion (pNode, &QuestionDefaultInfo);\r
2203\r
2204 //\r
2205 // Adjust the buffer content.\r
2206 // pStartAdjustNode->mIfrBinBuf points to the insert position.\r
2207 // pTailNode->mNext->mIfrBinBuf points to the inset opcodes.\r
2208 //\r
2209 pStartAdjustNode =GetRecordInfoFromOffset (gAdjustOpcodeOffset);\r
2210 gCFormPkg.AdjustDynamicInsertOpcode (pStartAdjustNode->mIfrBinBuf, pTailNode->mNext->mIfrBinBuf, TRUE);\r
2211\r
2212 //\r
2213 // Update the record info.\r
2214 //\r
2215 IfrUpdateRecordInfoForDynamicOpcode (TRUE);\r
2216 } else if (CheckDefault) {\r
2217 //\r
2218 // Generate an error for question which misses default.\r
2219 //\r
2220 MissingDefaultCount = mAllDefaultTypeCount - QuestionDefaultInfo.mDefaultNumber;\r
2221 sprintf (Msg, "The question misses %d default, the question's opcode is %d", MissingDefaultCount, pOpHead->OpCode);\r
2222 gCVfrErrorHandle.PrintMsg (pNode->mLineNo, NULL, "Error", Msg);\r
2223 }\r
2224 }\r
2225 }\r
2226 //\r
2227 // parse next opcode.\r
2228 //\r
2229 pNode = pNode->mNext;\r
2230 }\r
2231}\r
2232\r
30fdf114
LG
2233CIfrRecordInfoDB gCIfrRecordInfoDB;\r
2234\r
2235VOID\r
2236CIfrObj::_EMIT_PENDING_OBJ (\r
2237 VOID\r
2238 )\r
2239{\r
2240 CHAR8 *ObjBinBuf = NULL;\r
2241 \r
2242 //\r
2243 // do nothing\r
2244 //\r
2245 if (!mDelayEmit || !gCreateOp) {\r
2246 return;\r
2247 }\r
2248\r
2249 mPkgOffset = gCFormPkg.GetPkgLength ();\r
2250 //\r
2251 // update data buffer to package data\r
2252 //\r
2253 ObjBinBuf = gCFormPkg.IfrBinBufferGet (mObjBinLen);\r
2254 if (ObjBinBuf != NULL) {\r
f51461c8 2255 memmove (ObjBinBuf, mObjBinBuf, mObjBinLen);\r
30fdf114
LG
2256 }\r
2257 \r
2258 //\r
2259 // update bin buffer to package data buffer\r
2260 //\r
2261 if (mObjBinBuf != NULL) {\r
2262 delete mObjBinBuf;\r
2263 mObjBinBuf = ObjBinBuf;\r
2264 }\r
2265 \r
2266 mDelayEmit = FALSE;\r
2267}\r
2268\r
2269/*\r
2270 * The definition of CIfrObj's member function\r
2271 */\r
2272static struct {\r
2273 UINT8 mSize;\r
2274 UINT8 mScope;\r
2275} gOpcodeSizesScopeTable[] = {\r
2276 { 0, 0 }, // EFI_IFR_INVALID - 0x00\r
2277 { sizeof (EFI_IFR_FORM), 1 }, // EFI_IFR_FORM_OP\r
2278 { sizeof (EFI_IFR_SUBTITLE), 1 }, // EFI_IFR_SUBTITLE_OP\r
2279 { sizeof (EFI_IFR_TEXT), 0 }, // EFI_IFR_TEXT_OP\r
2280 { sizeof (EFI_IFR_IMAGE), 0 }, // EFI_IFR_IMAGE_OP\r
2281 { sizeof (EFI_IFR_ONE_OF), 1 }, // EFI_IFR_ONE_OF_OP - 0x05\r
2282 { sizeof (EFI_IFR_CHECKBOX), 1}, // EFI_IFR_CHECKBOX_OP\r
2283 { sizeof (EFI_IFR_NUMERIC), 1 }, // EFI_IFR_NUMERIC_OP\r
2284 { sizeof (EFI_IFR_PASSWORD), 1 }, // EFI_IFR_PASSWORD_OP\r
2285 { sizeof (EFI_IFR_ONE_OF_OPTION), 0 }, // EFI_IFR_ONE_OF_OPTION_OP\r
2286 { sizeof (EFI_IFR_SUPPRESS_IF), 1 }, // EFI_IFR_SUPPRESS_IF - 0x0A\r
2287 { sizeof (EFI_IFR_LOCKED), 0 }, // EFI_IFR_LOCKED_OP\r
2288 { sizeof (EFI_IFR_ACTION), 1 }, // EFI_IFR_ACTION_OP\r
2289 { sizeof (EFI_IFR_RESET_BUTTON), 1 }, // EFI_IFR_RESET_BUTTON_OP\r
2290 { sizeof (EFI_IFR_FORM_SET), 1 }, // EFI_IFR_FORM_SET_OP -0xE\r
2291 { sizeof (EFI_IFR_REF), 0 }, // EFI_IFR_REF_OP\r
2292 { sizeof (EFI_IFR_NO_SUBMIT_IF), 1}, // EFI_IFR_NO_SUBMIT_IF_OP -0x10\r
2293 { sizeof (EFI_IFR_INCONSISTENT_IF), 1 }, // EFI_IFR_INCONSISTENT_IF_OP\r
2294 { sizeof (EFI_IFR_EQ_ID_VAL), 0 }, // EFI_IFR_EQ_ID_VAL_OP\r
2295 { sizeof (EFI_IFR_EQ_ID_ID), 0 }, // EFI_IFR_EQ_ID_ID_OP\r
b303ea72 2296 { sizeof (EFI_IFR_EQ_ID_VAL_LIST), 0 }, // EFI_IFR_EQ_ID_LIST_OP - 0x14\r
30fdf114
LG
2297 { sizeof (EFI_IFR_AND), 0 }, // EFI_IFR_AND_OP\r
2298 { sizeof (EFI_IFR_OR), 0 }, // EFI_IFR_OR_OP\r
2299 { sizeof (EFI_IFR_NOT), 0 }, // EFI_IFR_NOT_OP\r
2300 { sizeof (EFI_IFR_RULE), 1 }, // EFI_IFR_RULE_OP\r
2301 { sizeof (EFI_IFR_GRAY_OUT_IF), 1 }, // EFI_IFR_GRAYOUT_IF_OP - 0x19\r
2302 { sizeof (EFI_IFR_DATE), 1 }, // EFI_IFR_DATE_OP\r
2303 { sizeof (EFI_IFR_TIME), 1 }, // EFI_IFR_TIME_OP\r
2304 { sizeof (EFI_IFR_STRING), 1 }, // EFI_IFR_STRING_OP\r
2305 { sizeof (EFI_IFR_REFRESH), 0 }, // EFI_IFR_REFRESH_OP\r
2306 { sizeof (EFI_IFR_DISABLE_IF), 1 }, // EFI_IFR_DISABLE_IF_OP - 0x1E\r
2307 { 0, 0 }, // 0x1F\r
2308 { sizeof (EFI_IFR_TO_LOWER), 0 }, // EFI_IFR_TO_LOWER_OP - 0x20\r
2309 { sizeof (EFI_IFR_TO_UPPER), 0 }, // EFI_IFR_TO_UPPER_OP - 0x21\r
52302d4d 2310 { sizeof (EFI_IFR_MAP), 1 }, // EFI_IFR_MAP - 0x22\r
30fdf114
LG
2311 { sizeof (EFI_IFR_ORDERED_LIST), 1 }, // EFI_IFR_ORDERED_LIST_OP - 0x23\r
2312 { sizeof (EFI_IFR_VARSTORE), 0 }, // EFI_IFR_VARSTORE_OP\r
2313 { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP\r
2314 { sizeof (EFI_IFR_VARSTORE_EFI), 0 }, // EFI_IFR_VARSTORE_EFI_OP\r
2315 { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 }, // EFI_IFR_VARSTORE_DEVICE_OP\r
2316 { sizeof (EFI_IFR_VERSION), 0 }, // EFI_IFR_VERSION_OP - 0x28\r
2317 { sizeof (EFI_IFR_END), 0 }, // EFI_IFR_END_OP\r
52302d4d
LG
2318 { sizeof (EFI_IFR_MATCH), 0 }, // EFI_IFR_MATCH_OP - 0x2A\r
2319 { sizeof (EFI_IFR_GET), 0 }, // EFI_IFR_GET - 0x2B\r
2320 { sizeof (EFI_IFR_SET), 0 }, // EFI_IFR_SET - 0x2C\r
2321 { sizeof (EFI_IFR_READ), 0 }, // EFI_IFR_READ - 0x2D\r
2322 { sizeof (EFI_IFR_WRITE), 0 }, // EFI_IFR_WRITE - 0x2E\r
30fdf114
LG
2323 { sizeof (EFI_IFR_EQUAL), 0 }, // EFI_IFR_EQUAL_OP - 0x2F\r
2324 { sizeof (EFI_IFR_NOT_EQUAL), 0 }, // EFI_IFR_NOT_EQUAL_OP\r
2325 { sizeof (EFI_IFR_GREATER_THAN), 0 }, // EFI_IFR_GREATER_THAN_OP\r
2326 { sizeof (EFI_IFR_GREATER_EQUAL), 0 }, // EFI_IFR_GREATER_EQUAL_OP\r
2327 { sizeof (EFI_IFR_LESS_THAN), 0 }, // EFI_IFR_LESS_THAN_OP\r
2328 { sizeof (EFI_IFR_LESS_EQUAL), 0 }, // EFI_IFR_LESS_EQUAL_OP - 0x34\r
2329 { sizeof (EFI_IFR_BITWISE_AND), 0 }, // EFI_IFR_BITWISE_AND_OP\r
2330 { sizeof (EFI_IFR_BITWISE_OR), 0 }, // EFI_IFR_BITWISE_OR_OP\r
2331 { sizeof (EFI_IFR_BITWISE_NOT), 0 }, // EFI_IFR_BITWISE_NOT_OP\r
2332 { sizeof (EFI_IFR_SHIFT_LEFT), 0 }, // EFI_IFR_SHIFT_LEFT_OP\r
2333 { sizeof (EFI_IFR_SHIFT_RIGHT), 0 }, // EFI_IFR_SHIFT_RIGHT_OP\r
2334 { sizeof (EFI_IFR_ADD), 0 }, // EFI_IFR_ADD_OP - 0x3A\r
2335 { sizeof (EFI_IFR_SUBTRACT), 0 }, // EFI_IFR_SUBTRACT_OP\r
2336 { sizeof (EFI_IFR_MULTIPLY), 0 }, // EFI_IFR_MULTIPLY_OP\r
2337 { sizeof (EFI_IFR_DIVIDE), 0 }, // EFI_IFR_DIVIDE_OP\r
2338 { sizeof (EFI_IFR_MODULO), 0 }, // EFI_IFR_MODULO_OP - 0x3E\r
2339 { sizeof (EFI_IFR_RULE_REF), 0 }, // EFI_IFR_RULE_REF_OP\r
2340 { sizeof (EFI_IFR_QUESTION_REF1), 0 }, // EFI_IFR_QUESTION_REF1_OP\r
2341 { sizeof (EFI_IFR_QUESTION_REF2), 0 }, // EFI_IFR_QUESTION_REF2_OP - 0x41\r
2342 { sizeof (EFI_IFR_UINT8), 0}, // EFI_IFR_UINT8\r
2343 { sizeof (EFI_IFR_UINT16), 0}, // EFI_IFR_UINT16\r
2344 { sizeof (EFI_IFR_UINT32), 0}, // EFI_IFR_UINT32\r
2345 { sizeof (EFI_IFR_UINT64), 0}, // EFI_IFR_UTNT64\r
2346 { sizeof (EFI_IFR_TRUE), 0 }, // EFI_IFR_TRUE_OP - 0x46\r
2347 { sizeof (EFI_IFR_FALSE), 0 }, // EFI_IFR_FALSE_OP\r
2348 { sizeof (EFI_IFR_TO_UINT), 0 }, // EFI_IFR_TO_UINT_OP\r
2349 { sizeof (EFI_IFR_TO_STRING), 0 }, // EFI_IFR_TO_STRING_OP\r
2350 { sizeof (EFI_IFR_TO_BOOLEAN), 0 }, // EFI_IFR_TO_BOOLEAN_OP\r
2351 { sizeof (EFI_IFR_MID), 0 }, // EFI_IFR_MID_OP\r
2352 { sizeof (EFI_IFR_FIND), 0 }, // EFI_IFR_FIND_OP\r
2353 { sizeof (EFI_IFR_TOKEN), 0 }, // EFI_IFR_TOKEN_OP\r
2354 { sizeof (EFI_IFR_STRING_REF1), 0 }, // EFI_IFR_STRING_REF1_OP - 0x4E\r
2355 { sizeof (EFI_IFR_STRING_REF2), 0 }, // EFI_IFR_STRING_REF2_OP\r
2356 { sizeof (EFI_IFR_CONDITIONAL), 0 }, // EFI_IFR_CONDITIONAL_OP\r
2357 { sizeof (EFI_IFR_QUESTION_REF3), 0 }, // EFI_IFR_QUESTION_REF3_OP\r
2358 { sizeof (EFI_IFR_ZERO), 0 }, // EFI_IFR_ZERO_OP\r
2359 { sizeof (EFI_IFR_ONE), 0 }, // EFI_IFR_ONE_OP\r
2360 { sizeof (EFI_IFR_ONES), 0 }, // EFI_IFR_ONES_OP\r
2361 { sizeof (EFI_IFR_UNDEFINED), 0 }, // EFI_IFR_UNDEFINED_OP\r
2362 { sizeof (EFI_IFR_LENGTH), 0 }, // EFI_IFR_LENGTH_OP\r
2363 { sizeof (EFI_IFR_DUP), 0 }, // EFI_IFR_DUP_OP - 0x57\r
2364 { sizeof (EFI_IFR_THIS), 0 }, // EFI_IFR_THIS_OP\r
2365 { sizeof (EFI_IFR_SPAN), 0 }, // EFI_IFR_SPAN_OP\r
2366 { sizeof (EFI_IFR_VALUE), 1 }, // EFI_IFR_VALUE_OP\r
2367 { sizeof (EFI_IFR_DEFAULT), 0 }, // EFI_IFR_DEFAULT_OP\r
2368 { sizeof (EFI_IFR_DEFAULTSTORE), 0 }, // EFI_IFR_DEFAULTSTORE_OP - 0x5C\r
52302d4d 2369 { sizeof (EFI_IFR_FORM_MAP), 1}, // EFI_IFR_FORM_MAP_OP - 0x5D\r
30fdf114
LG
2370 { sizeof (EFI_IFR_CATENATE), 0 }, // EFI_IFR_CATENATE_OP\r
2371 { sizeof (EFI_IFR_GUID), 0 }, // EFI_IFR_GUID_OP\r
a709adfa 2372 { sizeof (EFI_IFR_SECURITY), 0 }, // EFI_IFR_SECURITY_OP - 0x60\r
4afd3d04 2373 { sizeof (EFI_IFR_MODAL_TAG), 0}, // EFI_IFR_MODAL_TAG_OP - 0x61\r
4234283c 2374 { sizeof (EFI_IFR_REFRESH_ID), 0}, // EFI_IFR_REFRESH_ID_OP - 0x62\r
ea0f6464 2375 { sizeof (EFI_IFR_WARNING_IF), 1}, // EFI_IFR_WARNING_IF_OP - 0x63\r
5d377616 2376 { sizeof (EFI_IFR_MATCH2), 0 }, // EFI_IFR_MATCH2_OP - 0x64\r
30fdf114
LG
2377};\r
2378\r
2379#ifdef CIFROBJ_DEUBG\r
2380static struct {\r
2381 CHAR8 *mIfrName;\r
2382} gIfrObjPrintDebugTable[] = {\r
2383 "EFI_IFR_INVALID", "EFI_IFR_FORM", "EFI_IFR_SUBTITLE", "EFI_IFR_TEXT", "EFI_IFR_IMAGE", "EFI_IFR_ONE_OF",\r
2384 "EFI_IFR_CHECKBOX", "EFI_IFR_NUMERIC", "EFI_IFR_PASSWORD", "EFI_IFR_ONE_OF_OPTION", "EFI_IFR_SUPPRESS_IF", "EFI_IFR_LOCKED",\r
2385 "EFI_IFR_ACTION", "EFI_IFR_RESET_BUTTON", "EFI_IFR_FORM_SET", "EFI_IFR_REF", "EFI_IFR_NO_SUBMIT_IF", "EFI_IFR_INCONSISTENT_IF",\r
2386 "EFI_IFR_EQ_ID_VAL", "EFI_IFR_EQ_ID_ID", "EFI_IFR_EQ_ID_LIST", "EFI_IFR_AND", "EFI_IFR_OR", "EFI_IFR_NOT",\r
2387 "EFI_IFR_RULE", "EFI_IFR_GRAY_OUT_IF", "EFI_IFR_DATE", "EFI_IFR_TIME", "EFI_IFR_STRING", "EFI_IFR_REFRESH",\r
52302d4d 2388 "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID", "EFI_IFR_TO_LOWER", "EFI_IFR_TO_UPPER", "EFI_IFR_MAP", "EFI_IFR_ORDERED_LIST",\r
30fdf114 2389 "EFI_IFR_VARSTORE", "EFI_IFR_VARSTORE_NAME_VALUE", "EFI_IFR_VARSTORE_EFI", "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION", "EFI_IFR_END",\r
52302d4d 2390 "EFI_IFR_MATCH", "EFI_IFR_GET", "EFI_IFR_SET", "EFI_IFR_READ", "EFI_IFR_WRITE", "EFI_IFR_EQUAL",\r
30fdf114
LG
2391 "EFI_IFR_NOT_EQUAL", "EFI_IFR_GREATER_THAN", "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN", "EFI_IFR_LESS_EQUAL", "EFI_IFR_BITWISE_AND",\r
2392 "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT", "EFI_IFR_SHIFT_LEFT", "EFI_IFR_SHIFT_RIGHT", "EFI_IFR_ADD", "EFI_IFR_SUBTRACT",\r
2393 "EFI_IFR_MULTIPLY", "EFI_IFR_DIVIDE", "EFI_IFR_MODULO", "EFI_IFR_RULE_REF", "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2",\r
2394 "EFI_IFR_UINT8", "EFI_IFR_UINT16", "EFI_IFR_UINT32", "EFI_IFR_UINT64", "EFI_IFR_TRUE", "EFI_IFR_FALSE",\r
2395 "EFI_IFR_TO_UINT", "EFI_IFR_TO_STRING", "EFI_IFR_TO_BOOLEAN", "EFI_IFR_MID", "EFI_IFR_FIND", "EFI_IFR_TOKEN",\r
2396 "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2", "EFI_IFR_CONDITIONAL", "EFI_IFR_QUESTION_REF3", "EFI_IFR_ZERO", "EFI_IFR_ONE",\r
2397 "EFI_IFR_ONES", "EFI_IFR_UNDEFINED", "EFI_IFR_LENGTH", "EFI_IFR_DUP", "EFI_IFR_THIS", "EFI_IFR_SPAN",\r
52302d4d 2398 "EFI_IFR_VALUE", "EFI_IFR_DEFAULT", "EFI_IFR_DEFAULTSTORE", "EFI_IFR_FORM_MAP", "EFI_IFR_CATENATE", "EFI_IFR_GUID",\r
5d377616 2399 "EFI_IFR_SECURITY", "EFI_IFR_MODAL_TAG", "EFI_IFR_REFRESH_ID", "EFI_IFR_WARNING_IF", "EFI_IFR_MATCH2",\r
30fdf114
LG
2400};\r
2401\r
2402VOID\r
2403CIFROBJ_DEBUG_PRINT (\r
2404 IN UINT8 OpCode\r
2405 )\r
2406{\r
2407 printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName);\r
2408}\r
2409#else\r
2410\r
2411#define CIFROBJ_DEBUG_PRINT(OpCode)\r
2412\r
2413#endif\r
2414\r
52302d4d 2415BOOLEAN gCreateOp = TRUE;\r
30fdf114
LG
2416\r
2417CIfrObj::CIfrObj (\r
2418 IN UINT8 OpCode,\r
2419 OUT CHAR8 **IfrObj,\r
2420 IN UINT8 ObjBinLen,\r
2421 IN BOOLEAN DelayEmit\r
2422 )\r
2423{\r
2424 mDelayEmit = DelayEmit;\r
2425 mPkgOffset = gCFormPkg.GetPkgLength ();\r
2426 mObjBinLen = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen;\r
2427 mObjBinBuf = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH];\r
2428 mRecordIdx = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD;\r
b748e35c 2429 mLineNo = 0;\r
30fdf114 2430\r
9b78c54a
HW
2431 assert (mObjBinBuf != NULL);\r
2432\r
30fdf114
LG
2433 if (IfrObj != NULL) {\r
2434 *IfrObj = mObjBinBuf;\r
2435 }\r
2436\r
2437 CIFROBJ_DEBUG_PRINT (OpCode);\r
2438}\r
2439\r
2440CIfrObj::~CIfrObj (\r
2441 VOID\r
2442 )\r
2443{\r
2444 if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) {\r
2445 _EMIT_PENDING_OBJ ();\r
2446 }\r
2447\r
2448 gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset);\r
2449}\r
2450\r
2451/*\r
2452 * The definition of CIfrObj's member function\r
2453 */\r
2454UINT8 gScopeCount = 0;\r
2455\r
2456CIfrOpHeader::CIfrOpHeader (\r
2457 IN UINT8 OpCode,\r
2458 IN VOID *StartAddr,\r
2459 IN UINT8 Length\r
2460 ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr)\r
2461{\r
2462 mHeader->OpCode = OpCode;\r
2463 mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length;\r
2464 mHeader->Scope = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0;\r
2465}\r
2466\r
2467CIfrOpHeader::CIfrOpHeader (\r
2468 IN CIfrOpHeader &OpHdr\r
2469 )\r
2470{\r
2471 mHeader = OpHdr.mHeader;\r
2472}\r
2473\r
52302d4d 2474UINT32 CIfrFormId::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, };\r