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