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