]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/FCE/Fce.c
BaseTools/FCE: Add a tool FCE
[mirror_edk2.git] / BaseTools / Source / C / FCE / Fce.c
1 /** @file
2
3 FCE is a tool which enables developers to retrieve and change HII configuration ("Setup")
4 data in Firmware Device files (".fd" files).
5
6 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "Fce.h"
12
13 #ifndef __GNUC__
14 #define COPY_STR "copy \"%s\" \"%s\" > NUL"
15 #define RMDIR_STR "rmdir /S /Q \"%s\" > NUL"
16 #define DEL_STR "del \"%s\" > NUL"
17 #else
18 #define COPY_STR "cp \"%s\" \"%s\" > /dev/null"
19 #define RMDIR_STR "rm -r \"%s\" > /dev/null"
20 #define DEL_STR "rm \"%s\" > /dev/null"
21 #endif
22
23 //
24 // Utility global variables
25 //
26 OPERATION_TYPE Operations;
27
28 CHAR8 mInputFdName[MAX_FILENAME_LEN];
29 CHAR8 mOutputFdName[MAX_FILENAME_LEN];
30 CHAR8 mOutTxtName[MAX_FILENAME_LEN];
31 CHAR8 mSetupTxtName[MAX_FILENAME_LEN];
32
33 CHAR8* mUtilityFilename = NULL;
34 UINT32 mEfiVariableAddr = 0;
35
36 UQI_PARAM_LIST *mUqiList = NULL;
37 UQI_PARAM_LIST *mLastUqiList = NULL;
38 LIST_ENTRY mVarListEntry;
39 LIST_ENTRY mBfvVarListEntry;
40 LIST_ENTRY mAllVarListEntry;
41 LIST_ENTRY mFormSetListEntry;
42
43 //
44 // Store GUIDed Section guid->tool mapping
45 //
46 EFI_HANDLE mParsedGuidedSectionTools = NULL;
47
48 CHAR8* mGuidToolDefinition = "GuidToolDefinitionConf.ini";
49
50 //
51 //gFfsArray is used to store all the FFS informations of Fd
52 //
53 G_EFI_FD_INFO gEfiFdInfo;
54 //
55 //mMultiPlatformParam is used to store the structures about multi-platform support
56 //
57 MULTI_PLATFORM_PARAMETERS mMultiPlatformParam;
58
59 UINT32 mFormSetOrderRead;
60 UINT32 mFormSetOrderParse;
61
62 CHAR8 mFullGuidToolDefinitionDir[_MAX_PATH];
63
64 CHAR8 *mFvNameGuidString = NULL;
65
66 /**
67 Check the revision of BfmLib. If not matched, return an error.
68
69 @retval EFI_SUCCESS If revision matched, return EFI_SUCCESS.
70 @retval EFI_UNSUPPORTED Other cases.
71 **/
72 static
73 EFI_STATUS
74 CheckBfmLibRevision (
75 VOID
76 )
77 {
78 CHAR8 *SystemCommandFormatString;
79 CHAR8 *SystemCommand;
80 CHAR8 *TempSystemCommand;
81 CHAR8 *Revision;
82 FILE *FileHandle;
83 CHAR8 RevisionStr[_MAX_BUILD_VERSION];
84 UINT32 Len;
85
86 SystemCommandFormatString = NULL;
87 SystemCommand = NULL;
88 TempSystemCommand = NULL;
89 Revision = "Revision.txt";
90
91 memset (RevisionStr, 0, _MAX_BUILD_VERSION);
92
93 //
94 // Construction 'system' command string
95 //
96 SystemCommandFormatString = "BfmLib -v > %s";
97 SystemCommand = malloc (
98 strlen (SystemCommandFormatString) + strlen (Revision) + 1
99 );
100 if (SystemCommand == NULL) {
101 return EFI_UNSUPPORTED;
102 }
103 sprintf (
104 SystemCommand,
105 "BfmLib -v > %s",
106 Revision
107 );
108
109 if (mFullGuidToolDefinitionDir[0] != 0) {
110 TempSystemCommand = SystemCommand;
111 SystemCommand = malloc (
112 strlen (mFullGuidToolDefinitionDir) + strlen (OS_SEP_STR) + strlen (SystemCommandFormatString) + strlen (Revision) + 1
113 );
114
115 if (SystemCommand == NULL) {
116 free (TempSystemCommand);
117 return EFI_UNSUPPORTED;
118 }
119 strcpy (SystemCommand, mFullGuidToolDefinitionDir);
120 strcat (SystemCommand, OS_SEP_STR);
121 strcat (SystemCommand, TempSystemCommand);
122 free (TempSystemCommand);
123 }
124
125 system (SystemCommand);
126 free (SystemCommand);
127 FileHandle = fopen (Revision, "r");
128 if (FileHandle == NULL) {
129 printf ("Error. Read the revision file of BfmLib failed.\n");
130 return EFI_ABORTED;
131 }
132 fgets(RevisionStr, _MAX_BUILD_VERSION, FileHandle);
133 Len = strlen(RevisionStr);
134 if (RevisionStr[Len - 1] == '\n') {
135 RevisionStr[Len - 1] = 0;
136 }
137 fclose (FileHandle);
138 remove (Revision);
139
140 if (strlen (RevisionStr) > _MAX_BUILD_VERSION - 1) {
141 printf ("The revision string is too long");
142 return EFI_UNSUPPORTED;
143 }
144 if (strcmp (RevisionStr, __BUILD_VERSION) == 0) {
145 return EFI_SUCCESS;
146 }
147 return EFI_UNSUPPORTED;
148 }
149
150 /**
151 Transfer the Ascii string to the Dec Number
152
153 @param InStr The Ascii string.
154
155 @retval DecNum Return the Dec number.
156 **/
157 static
158 UINT64
159 StrToDec (
160 IN CHAR8 *InStr
161 )
162 {
163 UINT8 Index;
164 UINTN DecNum;
165 UINTN Temp;
166
167 Index = 0;
168 DecNum = 0;
169 Temp = 0;
170
171 if (InStr == NULL) {
172 return (UINT64)-1;
173 }
174 while (Index < strlen (InStr)) {
175
176 if ((*(InStr + Index) >= '0') && (*(InStr + Index) <= '9')) {
177 Temp = *(InStr + Index) - '0';
178 } else if ((*(InStr + Index) >= 'a') && (*(InStr + Index) <= 'f')) {
179 Temp = *(InStr + Index) - 'a' + 10;
180 } else if ((*(InStr + Index) >= 'A') && (*(InStr + Index) <= 'F')) {
181 Temp = *(InStr + Index) - 'A' + 10;
182 }
183 DecNum = DecNum + Temp * (UINTN) pow (16, strlen (InStr) - Index - 1);
184 Index++;
185 }
186 return DecNum;
187 }
188 /**
189 Check whether there are some errors in uqi parameters of One_of
190
191 @param Question The pointer to the question Node.
192 @param UqiValue The value of One_of.
193
194 @retval TRUE If existed error, return TRUE;
195 @return FALSE Otherwise, return FALSE;
196 **/
197 static
198 BOOLEAN
199 CheckOneOfParamError (
200 IN CONST FORM_BROWSER_STATEMENT *Question,
201 IN UINT64 UqiValue
202 )
203 {
204 LIST_ENTRY *Link;
205 QUESTION_OPTION *Option;
206 UINT64 Value;
207
208 Link = NULL;
209 Option = NULL;
210 Value = 0;
211
212 Link = GetFirstNode (&Question->OptionListHead);
213 while (!IsNull (&Question->OptionListHead, Link)) {
214 Option = QUESTION_OPTION_FROM_LINK (Link);
215 Value = 0;
216 CopyMem (&Value, &Option->Value.Value.u64, Question->StorageWidth);
217 if (Value == UqiValue) {
218 return FALSE;
219 }
220 Link = GetNextNode (&Question->OptionListHead, Link);
221 }
222
223 return TRUE;
224 }
225
226 /**
227 Check whether there are some errors in uqi parameters of Orderlist
228
229 @param HiiObjList The pointer to the Hii Object Node.
230 @param UqiValue The pointer to the Uqi parameter.
231
232 @retval TRUE If existed error, return TRUE;
233 @return FALSE Otherwise, return FALSE;
234 **/
235 static
236 BOOLEAN
237 CheckOrderParamError (
238 IN CONST FORM_BROWSER_STATEMENT *Question,
239 IN CHAR8 *UqiValue
240 )
241 {
242 UINT8 MaxNum;
243 MaxNum = UqiValue[0];
244
245 if (MaxNum != (UINT8)(Question->MaxContainers)) {
246 return TRUE;
247 }
248
249 return FALSE;
250 }
251
252 /**
253 Writes a Unicode string
254
255 @param Package A pointer to the Unicode string.
256
257 @return NULL
258 **/
259 static
260 VOID
261 WriteUnicodeStr (
262 IN CHAR16 *pcString
263 )
264 {
265 UINTN Index;
266
267 if (pcString == NULL) {
268 return;
269 }
270
271 for (Index = 0; pcString[Index] != 0; Index++) {
272 printf("%c", pcString[Index] & 0x00FF);
273 }
274 }
275
276 /**
277 Parse and set the quick configure information by the command line.
278
279 Read the UQI Config information from command line directly, and then compare it with the value in VarList.
280 Update the Update flag in Varlist.
281
282 @param CurUqiList The pointer to the current uqi
283 @param DefaultId The default Id.
284 @param PlatformId The platform Id.
285 @param CurQuestion The pointer to the matched question
286
287 @retval EFI_SUCCESS It was complete successfully
288 @retval EFI_UNSUPPORTED Update a read-only value
289 @return EFI_ABORTED An error occurred
290 **/
291 static
292 EFI_STATUS
293 SetUqiParametersWithQuestion (
294 IN UQI_PARAM_LIST *CurUqiList,
295 IN UINT16 DefaultId,
296 IN UINT64 PlatformId,
297 IN FORM_BROWSER_STATEMENT *CurQuestion
298 )
299 {
300 FORMSET_STORAGE *VarList;
301 BOOLEAN IsFound;
302 UINT8 *ValueAddrOfVar;
303 UINT16 Index;
304 UINT64 QuestionValue;
305 UINT64 UqiValue;
306 EFI_STATUS Status;
307 CHAR8 *ErrorStr;
308 FORM_BROWSER_FORMSET *FormSet;
309 LIST_ENTRY *FormSetLink;
310 UINT64 CurValue;
311
312 VarList = NULL;
313 Index = 0;
314 ValueAddrOfVar = NULL;
315 QuestionValue = 0;
316 UqiValue = 0;
317 ErrorStr = NULL;
318 Status = EFI_SUCCESS;
319 FormSet = NULL;
320 FormSetLink = NULL;
321 CurValue = 0;
322
323 //
324 // Search the Variable List by VarStoreId and Offset
325 //
326 IsFound = FALSE;
327 FormSetLink = GetFirstNode (&mFormSetListEntry);
328 while (!IsNull (&mFormSetListEntry, FormSetLink)) {
329 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
330 Status = SearchVarStorage (
331 CurQuestion,
332 NULL,
333 CurQuestion->VarStoreInfo.VarOffset,
334 FormSet->StorageListHead,
335 (CHAR8 **) &ValueAddrOfVar,
336 &VarList
337 );
338
339 if (!EFI_ERROR (Status)) {
340 IsFound = TRUE;
341 break;
342 }
343 FormSetLink = GetNextNode (&mFormSetListEntry, FormSetLink);
344 }
345
346 if (!IsFound) {
347 if (CurUqiList->Header.ScriptsLine == 0) {
348 printf ("Error. The question in the command line doesn't store value by EFI_VARSTORE_IFR or EFI_VARSTORE_IFR_EFI.\n");
349 } else {
350 printf ("Error. The question in the line %d of script doesn't store value by EFI_VARSTORE_IFR or EFI_VARSTORE_IFR_EFI.\n", CurUqiList->Header.ScriptsLine);
351 }
352 return EFI_ABORTED;
353 }
354
355 //
356 // Check the length of variable value
357 //
358 if (CurQuestion->QuestionReferToBitField) {
359 GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)&QuestionValue);
360 } else {
361 switch (CurQuestion->StorageWidth) {
362
363 case sizeof (UINT8):
364 QuestionValue = *(UINT8 *)ValueAddrOfVar;
365 break;
366
367 case sizeof (UINT16):
368 QuestionValue = *(UINT16 *)ValueAddrOfVar;
369 break;
370
371 case sizeof (UINT32):
372 QuestionValue = *(UINT32 *)ValueAddrOfVar;
373 break;
374
375 case sizeof (UINT64):
376 QuestionValue = *(UINT64 *)ValueAddrOfVar;
377 break;
378
379 default:
380 //
381 // The storage width of ORDERED_LIST may not be any type above.
382 //
383 ;
384 break;
385 }
386 }
387 UqiValue = *(UINT64 *)CurUqiList->Header.Value;
388 CurUqiList->SameOrNot = TRUE;
389
390 //
391 // Check and set the checkbox value
392 //
393 if (CurQuestion->Operand == EFI_IFR_CHECKBOX_OP) {
394 if ((UqiValue != 0) && (UqiValue != 1)) {
395 CurUqiList->ErrorOrNot = TRUE;
396 CurUqiList->SameOrNot = FALSE;
397 CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8));
398 if (CurUqiList->Error == NULL) {
399 printf ("Fail to allocate memory!\n");
400 return EFI_ABORTED;
401 }
402 memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH);
403 sprintf (CurUqiList->Error, "Error. The updated value of CHECKBOX 0x%llx is invalid.\n", (unsigned long long) UqiValue);
404 if (CurQuestion->QuestionReferToBitField) {
405 GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue);
406 } else {
407 memcpy (
408 CurUqiList->Header.DiffValue,
409 ValueAddrOfVar,
410 CurQuestion->StorageWidth
411 );
412 }
413 } else {
414 if (QuestionValue != UqiValue) {
415 if (CurQuestion->QuestionReferToBitField) {
416 GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue);
417 SetBitsQuestionValue (CurQuestion, ValueAddrOfVar, *(UINT32*)CurUqiList->Header.Value);
418 } else {
419 memcpy (
420 CurUqiList->Header.DiffValue,
421 ValueAddrOfVar,
422 CurQuestion->StorageWidth
423 );
424 memcpy (
425 ValueAddrOfVar,
426 CurUqiList->Header.Value,
427 CurQuestion->StorageWidth
428 );
429 }
430 CurUqiList->SameOrNot = FALSE;
431 }
432 }
433 }
434 if (CurQuestion->Operand == EFI_IFR_STRING_OP) {
435 if ((FceStrLen((wchar_t *)CurUqiList->Header.Value) + 1) * 2 > CurQuestion->StorageWidth) {
436 CurUqiList->ErrorOrNot = TRUE;
437 CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8));
438 if (CurUqiList->Error == NULL) {
439 printf ("Fail to allocate memory!\n");
440 return EFI_ABORTED;
441 }
442 memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH);
443 sprintf (CurUqiList->Error, "Error. The updated value of STRING exceed its Size.\n");
444 memcpy (
445 CurUqiList->Header.DiffValue,
446 ValueAddrOfVar,
447 CurQuestion->StorageWidth
448 );
449 } else {
450 if (memcmp((CHAR8 *)CurUqiList->Header.Value, ValueAddrOfVar, CurQuestion->StorageWidth) != 0) {
451 memcpy(
452 CurUqiList->Header.DiffValue,
453 ValueAddrOfVar,
454 CurQuestion->StorageWidth
455 );
456 memcpy(
457 ValueAddrOfVar,
458 CurUqiList->Header.Value,
459 CurQuestion->StorageWidth
460 );
461 CurUqiList->SameOrNot = FALSE;
462 }
463 }
464 }
465 //
466 // Check and set the NUMERIC value
467 //
468 if (CurQuestion->Operand == EFI_IFR_NUMERIC_OP) {
469 if ((UqiValue < CurQuestion->Minimum) || (UqiValue > CurQuestion->Maximum)) {
470 CurUqiList->ErrorOrNot = TRUE;
471 CurUqiList->SameOrNot = FALSE;
472 CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8));
473 if (CurUqiList->Error == NULL) {
474 printf ("Fail to allocate memory!\n");
475 return EFI_ABORTED;
476 }
477 memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH);
478 sprintf (CurUqiList->Error, "Error. The updated value of NUMERIC 0x%llx is invalid.\n", (unsigned long long) UqiValue);
479 if (CurQuestion->QuestionReferToBitField) {
480 GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue);
481 } else {
482 memcpy (
483 CurUqiList->Header.DiffValue,
484 ValueAddrOfVar,
485 CurQuestion->StorageWidth
486 );
487 }
488 } else {
489 if (QuestionValue != UqiValue) {
490 if (CurQuestion->QuestionReferToBitField) {
491 GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue);
492 SetBitsQuestionValue (CurQuestion, ValueAddrOfVar, *(UINT32*)CurUqiList->Header.Value);
493 } else {
494 memcpy (
495 CurUqiList->Header.DiffValue,
496 ValueAddrOfVar,
497 CurQuestion->StorageWidth
498 );
499 memcpy (
500 ValueAddrOfVar,
501 CurUqiList->Header.Value,
502 CurQuestion->StorageWidth
503 );
504 }
505 CurUqiList->SameOrNot = FALSE;
506 }
507 }
508 }
509 //
510 // Check and set the ONE_OF value
511 //
512 if (CurQuestion->Operand == EFI_IFR_ONE_OF_OP) {
513 if (CheckOneOfParamError (CurQuestion, UqiValue)) {
514 CurUqiList->ErrorOrNot = TRUE;
515 CurUqiList->SameOrNot = FALSE;
516 CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8));
517 if (CurUqiList->Error == NULL) {
518 printf ("Fail to allocate memory!\n");
519 return EFI_ABORTED;
520 }
521 memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH);
522 sprintf (CurUqiList->Error, "Error. The updated ONE_OF value 0x%llx is invalid.\n", (unsigned long long) UqiValue);
523 if (CurQuestion->QuestionReferToBitField) {
524 GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue);
525 } else {
526 memcpy (
527 CurUqiList->Header.DiffValue,
528 ValueAddrOfVar,
529 CurQuestion->StorageWidth
530 );
531 }
532 } else {
533 if (QuestionValue != UqiValue) {
534 if (CurQuestion->QuestionReferToBitField) {
535 GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue);
536 SetBitsQuestionValue (CurQuestion, ValueAddrOfVar, *(UINT32*)CurUqiList->Header.Value);
537 } else {
538 memcpy (
539 CurUqiList->Header.DiffValue,
540 ValueAddrOfVar,
541 CurQuestion->StorageWidth
542 );
543 memcpy (
544 ValueAddrOfVar,
545 CurUqiList->Header.Value,
546 CurQuestion->StorageWidth
547 );
548 }
549 CurUqiList->SameOrNot = FALSE;
550 }
551 }
552 }
553 //
554 // Check and set the ORDER_LIST value
555 //
556 if (CurQuestion->Operand == EFI_IFR_ORDERED_LIST_OP) {
557 //
558 // Synchronize the MaxContainers value
559 //
560 *CurUqiList->Header.DiffValue = (UINT8)CurQuestion->MaxContainers;
561
562 if (CheckOrderParamError (CurQuestion, (CHAR8 *)CurUqiList->Header.Value)) {
563
564 CurUqiList->ErrorOrNot = TRUE;
565 CurUqiList->SameOrNot = FALSE;
566 CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8));
567 if (CurUqiList->Error == NULL) {
568 printf ("Fail to allocate memory!\n");
569 return EFI_ABORTED;
570 }
571 memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH);
572
573 ErrorStr = CurUqiList->Error;
574 sprintf (ErrorStr, "Error. The updated NORDERED_LIST value ");
575 ErrorStr = ErrorStr + strlen ("Error. The updated NORDERED_LIST value ");
576
577 for (Index = 0; Index < CurQuestion->StorageWidth; Index++) {
578 sprintf (ErrorStr, "%02x ", *(CurUqiList->Header.Value + Index + 1));
579 ErrorStr +=3;
580 }
581 sprintf (ErrorStr, "is invalid.\n");
582 memcpy (
583 CurUqiList->Header.DiffValue + 1,
584 ValueAddrOfVar,
585 CurQuestion->StorageWidth
586 );
587 } else {
588 for (Index = 0; Index < CurQuestion->StorageWidth/CurQuestion->MaxContainers; Index++) {
589 CurValue = 0;
590 memcpy (
591 &CurValue,
592 (ValueAddrOfVar + Index * CurQuestion->StorageWidth/CurQuestion->MaxContainers),
593 CurQuestion->StorageWidth/CurQuestion->MaxContainers
594 );
595 if (CurValue != *((UINT64 *)CurUqiList->Header.Value + Index + 1)) {
596 CurUqiList->SameOrNot = FALSE;
597 break;
598 }
599 }
600 if (!CurUqiList->SameOrNot) {
601 memcpy (
602 CurUqiList->Header.DiffValue + 1,
603 ValueAddrOfVar,
604 CurQuestion->StorageWidth
605 );
606 for (Index = 0; Index < CurQuestion->MaxContainers; Index++) {
607 switch (CurQuestion->StorageWidth/CurQuestion->MaxContainers) {
608
609 case sizeof (UINT8):
610 *((UINT8 *)ValueAddrOfVar + Index) = *(UINT8 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index);
611 break;
612
613 case sizeof (UINT16):
614 *((UINT16 *)ValueAddrOfVar + Index) = *(UINT16 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index);
615 break;
616
617 case sizeof (UINT32):
618 *((UINT32 *)ValueAddrOfVar + Index) = *(UINT32 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index);
619 break;
620
621 case sizeof (UINT64):
622 *((UINT64 *)ValueAddrOfVar + Index) = *((UINT64 *)CurUqiList->Header.Value + 1 + Index);
623 break;
624
625 default:
626 *((UINT8 *)ValueAddrOfVar + Index) = *(UINT8 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index);
627 break;
628 }
629 }
630 //
631 // Update the vaule of ORDERED_LIST according to its size
632 //
633 CurUqiList->Header.Value = (UINT8 *)((UINT64 *)CurUqiList->Header.Value);
634 memcpy (
635 CurUqiList->Header.Value + 1,
636 ValueAddrOfVar,
637 CurQuestion->StorageWidth
638 );
639 }
640 }
641 }
642
643 return EFI_SUCCESS;
644 }
645
646 /**
647 Parse and set the quick configure information by the command line.
648
649 Read the UQI Config information from command line directly, and then compare it with the value in VarList.
650 Update the Update flag in Varlist.
651
652 @param UqiList The pointer to the uqi list
653 @param DefaultId The default Id.
654 @param PlatformId The platform Id.
655
656 @retval EFI_SUCCESS It was complete successfully
657 @retval EFI_UNSUPPORTED Update a read-only value
658 @return EFI_ABORTED An error occurred
659 **/
660 static
661 EFI_STATUS
662 SetUqiParameters (
663 IN UQI_PARAM_LIST *UqiList,
664 IN UINT16 DefaultId,
665 IN UINT64 PlatformId
666 )
667 {
668 FORM_BROWSER_FORMSET *FormSet;
669 LIST_ENTRY *FormSetLink;
670 FORM_BROWSER_FORM *Form;
671 LIST_ENTRY *FormLink;
672 FORM_BROWSER_STATEMENT *Question;
673 LIST_ENTRY *QuestionLink;
674 LIST_ENTRY *FormSetEntryListHead;
675 UQI_PARAM_LIST *CurUqiList;
676
677 FormSet = NULL;
678 FormSetLink = NULL;
679 Form = NULL;
680 FormLink = NULL;
681 Question = NULL;
682 QuestionLink = NULL;
683 FormSetEntryListHead = &mFormSetListEntry;
684
685 FormSetLink = GetFirstNode (FormSetEntryListHead);
686 while (!IsNull (FormSetEntryListHead, FormSetLink)) {
687 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
688 //
689 // Parse all forms in formset
690 //
691 FormLink = GetFirstNode (&FormSet->FormListHead);
692
693 while (!IsNull (&FormSet->FormListHead, FormLink)) {
694 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
695 //
696 // Parse five kinds of Questions in Form
697 //
698 QuestionLink = GetFirstNode (&Form->StatementListHead);
699
700 while (!IsNull (&Form->StatementListHead, QuestionLink)) {
701 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
702 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
703 //
704 // Parse five kinds of Questions in Form
705 //
706 if ((Question->Operand == EFI_IFR_ONE_OF_OP)
707 || (Question->Operand == EFI_IFR_NUMERIC_OP)
708 || (Question->Operand == EFI_IFR_CHECKBOX_OP)
709 || (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
710 || (Question->Operand == EFI_IFR_STRING_OP)
711 ) {
712 if (mMultiPlatformParam.MultiPlatformOrNot) {
713 //
714 // Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode
715 //
716 if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) {
717 continue;
718 }
719 if ((Question->Type == EFI_IFR_VARSTORE_EFI_OP)
720 && Question->NewEfiVarstore
721 && ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {
722 continue;
723 }
724 }
725
726 CurUqiList = UqiList;
727 while (CurUqiList != NULL) {
728 if ((PlatformId == CurUqiList->Header.PlatformId[0])
729 && (DefaultId == CurUqiList->Header.DefaultId[0])
730 && CompareUqiHeader (&(Question->Uqi), &(CurUqiList->Header))
731 ) {
732 //
733 // Add further check to avoid a case that there are many options with a
734 // same UQI (en-Us), but always returns the first one.
735 //
736 if (!CurUqiList->ParseOrNot) {
737 CurUqiList->ParseOrNot = TRUE;
738 break;
739 }
740 }
741 CurUqiList = CurUqiList->Next;
742 }
743 if (CurUqiList != NULL) {
744 SetUqiParametersWithQuestion (CurUqiList, DefaultId, PlatformId, Question);
745 }
746 }
747 }
748 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
749 }
750 FormSetLink = GetNextNode (FormSetEntryListHead, FormSetLink);
751 }
752
753 return EFI_SUCCESS;
754 }
755
756 /**
757 Set question value per UqiList.
758
759 @param UqiList The pointer to the uqi list
760 @param DefaultId The default Id.
761 @param PlatformId The platform Id.
762 **/
763 VOID
764 SetUqiParametersMultiMode (
765 IN UQI_PARAM_LIST *UqiList,
766 IN UINT16 DefaultId,
767 IN UINT64 PlatformId
768 )
769 {
770 UQI_PARAM_LIST *CurUqiList;
771
772 CurUqiList = UqiList;
773 while (CurUqiList != NULL) {
774 if ((CurUqiList->ParseOrNot == FALSE)
775 && (PlatformId == CurUqiList->Header.PlatformId[0])
776 && (DefaultId == CurUqiList->Header.DefaultId[0])
777 ) {
778 CurUqiList->ParseOrNot = TRUE;
779 if (CurUqiList->Header.Question != NULL) {
780 SetUqiParametersWithQuestion (CurUqiList, DefaultId, PlatformId, CurUqiList->Header.Question);
781 }
782 }
783 CurUqiList = CurUqiList->Next;
784 }
785 }
786
787 /**
788 Find the matched question for each UQI string in UqiList
789
790 **/
791 EFI_STATUS
792 ScanUqiFullList (
793 IN UQI_PARAM_LIST *UqiList
794 )
795 {
796 FORM_BROWSER_FORMSET *FormSet;
797 LIST_ENTRY *FormSetLink;
798 FORM_BROWSER_FORM *Form;
799 LIST_ENTRY *FormLink;
800 FORM_BROWSER_STATEMENT *Question;
801 LIST_ENTRY *QuestionLink;
802 LIST_ENTRY *FormSetEntryListHead;
803 UQI_PARAM_LIST *CurUqiList;
804 UINT64 PlatformId;
805 UINT16 DefaultId;
806
807 if (UqiList == NULL) {
808 return EFI_SUCCESS;
809 }
810 FormSet = NULL;
811 FormSetLink = NULL;
812 Form = NULL;
813 FormLink = NULL;
814 Question = NULL;
815 QuestionLink = NULL;
816 FormSetEntryListHead = &mFormSetListEntry;
817
818 FormSetLink = FormSetEntryListHead->ForwardLink;
819 while (FormSetEntryListHead != FormSetLink) {
820 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
821 //
822 // Parse all forms in formset
823 //
824 FormLink = FormSet->FormListHead.ForwardLink;
825
826 while (&FormSet->FormListHead != FormLink) {
827 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
828 //
829 // Parse five kinds of Questions in Form
830 //
831 QuestionLink = Form->StatementListHead.ForwardLink;
832
833 while (&Form->StatementListHead != QuestionLink) {
834 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
835 QuestionLink = QuestionLink->ForwardLink;
836 //
837 // Parse five kinds of Questions in Form
838 //
839 if ((Question->Operand == EFI_IFR_ONE_OF_OP)
840 || (Question->Operand == EFI_IFR_NUMERIC_OP)
841 || (Question->Operand == EFI_IFR_CHECKBOX_OP)
842 || (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
843 || (Question->Operand == EFI_IFR_STRING_OP)
844 ) {
845 //
846 // Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode
847 //
848 if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) {
849 continue;
850 } else if (Question->NewEfiVarstore
851 && ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {
852 continue;
853 }
854
855 CurUqiList = UqiList;
856 PlatformId = 0xFFFFFFFF;
857 DefaultId = 0xFFFF;
858 while (CurUqiList != NULL) {
859 if ((CurUqiList->Header.Question == NULL)
860 && CompareUqiHeader (&(Question->Uqi), &(CurUqiList->Header))
861 && ((PlatformId != CurUqiList->Header.PlatformId[0]) || (DefaultId != CurUqiList->Header.DefaultId[0]))
862 ) {
863 CurUqiList->Header.Question = Question;
864 PlatformId = CurUqiList->Header.PlatformId[0];
865 DefaultId = CurUqiList->Header.DefaultId[0];
866 }
867 CurUqiList = CurUqiList->Next;
868 }
869 }
870 }
871 FormLink = FormLink->ForwardLink;
872 }
873 FormSetLink = FormSetLink->ForwardLink;
874 }
875
876 return EFI_SUCCESS;
877 }
878
879 /**
880 Create and insert the UQI Node to the UQI parameter list.
881
882 @retval Node address If successed, return the node address.
883 @retval NULL An error occurred.
884
885 **/
886 static
887 UQI_PARAM_LIST *
888 CreateInsertUqiNode (
889 )
890 {
891 UQI_PARAM_LIST *Node;
892
893 Node = (UQI_PARAM_LIST *) malloc (sizeof (UQI_PARAM_LIST));
894 if (Node == NULL) {
895 return NULL;
896 }
897 memset (Node, 0, sizeof (UQI_PARAM_LIST));
898
899 if (mUqiList == NULL) {
900 mUqiList = Node;
901 } else {
902 mLastUqiList->Next = Node;
903 }
904
905 mLastUqiList = Node;
906 return Node;
907 }
908 /**
909 Parse the first part of QUI string
910
911 @param **argv[] The dual array pointer to the parameters.
912 @param Number The pointer to the number of the first character of UQI.
913 @param Buffer The buffer to store the first part of UQI.
914
915 @retval EFI_SUCCESS Parse the QUI parameters successfully.
916 @retval EFI_INVALID_PARAMETER An error occurred.
917
918 **/
919 static
920 EFI_STATUS
921 ParseFirstpartOfUqi (
922 IN CHAR8 **argv[],
923 OUT UINT32 *Number,
924 OUT UINT16 **Buffer
925 )
926 {
927 UINT32 Index;
928
929 Index = 0;
930
931 *Number = (UINT32)StrToDec ((*argv)[0]);
932
933 if ((*Number <= 0) || (*Number > MAX_QUI_PARAM_LEN)) {
934 printf ("Error. Invalid UQI.\n");
935 return EFI_INVALID_PARAMETER;
936 }
937
938 *Buffer = malloc ((*Number + 1) * sizeof (CHAR16));
939 assert (*Buffer != NULL);
940 memset (*Buffer, 0, (*Number + 1) * sizeof (CHAR16));
941
942 for (Index = 0; Index < *Number; Index++) {
943 if (StrToDec ((*argv)[Index]) > 0xff) {
944 printf ("Error. Invalid UQI.\n");
945 return EFI_INVALID_PARAMETER;
946 }
947 *(*Buffer + Index) = (UINT16)StrToDec ((*argv)[Index + 1]);
948 }
949 return EFI_SUCCESS;
950 }
951
952 /**
953 Parse the QUI input parameters from the command line
954
955 @param argc The pointer to the number of input parameters.
956 @param **argv[] The dual array pointer to the parameters.
957
958 @retval EFI_SUCCESS Parse the QUI parameters successfully.
959 @retval EFI_INVALID_PARAMETER An error occurred.
960
961 **/
962 static
963 EFI_STATUS
964 ParseUqiParam (
965 IN UINT32 *argc,
966 IN CHAR8 **argv[]
967 )
968 {
969 UINT32 Index;
970 UQI_PARAM_LIST *UqiNode;
971 EFI_STATUS Status;
972
973 Index = 0;
974 UqiNode = NULL;
975
976 if (*argc < 4) {
977 printf ("Error. The correct command is 'FCE updateq -i <infd> -o <outfd> <UQI> <Question Type> <Value>'.\n");
978 return EFI_INVALID_PARAMETER;
979 }
980
981 UqiNode = CreateInsertUqiNode ();
982 assert (UqiNode != NULL);
983
984 UqiNode->Header.DefaultId = (UINT16 *) calloc (1, sizeof (UINT16));
985 UqiNode->Header.PlatformId = (UINT64 *) calloc (1, sizeof (UINT64));
986
987 Status = ParseFirstpartOfUqi (argv, &(UqiNode->Header.HexNum), &(UqiNode->Header.Data));
988 if (EFI_ERROR (Status)) {
989 return Status;
990 }
991 *argc -= (UqiNode->Header.HexNum + 1);
992 *argv += UqiNode->Header.HexNum + 1;
993 //
994 // Parse the TYPE and value
995 //
996 if (strcmp ("ONE_OF", (*argv)[0]) == 0) {
997 UqiNode->Header.Type = ONE_OF;
998 } else if (strcmp ("NUMERIC", (*argv)[0]) == 0) {
999 UqiNode->Header.Type = NUMERIC;
1000 } else if (strcmp ("CHECKBOX", (*argv)[0]) == 0) {
1001 UqiNode->Header.Type = CHECKBOX;
1002 } else if (strcmp ("STRING", (*argv)[0]) == 0) {
1003 UqiNode->Header.Type = STRING;
1004 } else if (strcmp ("ORDERED_LIST", (*argv)[0]) == 0) {
1005 UqiNode->Header.Type = ORDERED_LIST;
1006 } else {
1007 printf ("Error. The correct command is 'FCE updateq -i <infd> -o <outfd> <UQI> <Question Type> <Value>'.\n");
1008 return EFI_INVALID_PARAMETER;
1009 }
1010 *argc -= 1;
1011 *argv += 1;
1012 //
1013 // Get the value according to the type of questions.
1014 //
1015 switch (UqiNode->Header.Type) {
1016
1017 case ONE_OF:
1018 case NUMERIC:
1019 case CHECKBOX:
1020 UqiNode->Header.Value = malloc (sizeof (UINT64));
1021 if (UqiNode->Header.Value == NULL) {
1022 printf ("Fali to allocate memory!\n");
1023 return EFI_OUT_OF_RESOURCES;
1024 }
1025 memset (UqiNode->Header.Value, 0, sizeof (UINT64));
1026
1027 UqiNode->Header.DiffValue = malloc (sizeof (UINT64));
1028 if (UqiNode->Header.DiffValue == NULL) {
1029 printf ("Fali to allocate memory!\n");
1030 return EFI_OUT_OF_RESOURCES;
1031 }
1032 memset (
1033 UqiNode->Header.DiffValue,
1034 0,
1035 sizeof (UINT64)
1036 );
1037 *(UINT64 *)(UqiNode->Header.Value) = (UINT64)StrToDec ((*argv)[0]);
1038 break;
1039
1040 case ORDERED_LIST:
1041 UqiNode->Header.Value = malloc (((UINTN)StrToDec ((*argv)[0]) + 1) * sizeof (UINT64));
1042 if (UqiNode->Header.Value == NULL) {
1043 printf ("Fali to allocate memory!\n");
1044 return EFI_OUT_OF_RESOURCES;
1045 }
1046 memset (
1047 UqiNode->Header.Value,
1048 0,
1049 (UINTN)StrToDec(((*argv)[0]) + 1) * sizeof (UINT64)
1050 );
1051
1052 UqiNode->Header.DiffValue = malloc (((UINTN)StrToDec ((*argv)[0]) + 1) * sizeof (UINT64));
1053 if (UqiNode->Header.DiffValue == NULL) {
1054 printf ("Fali to allocate memory!\n");
1055 return EFI_OUT_OF_RESOURCES;
1056 }
1057 memset (
1058 UqiNode->Header.DiffValue,
1059 0,
1060 (UINTN)(StrToDec ((*argv)[0]) + 1) * sizeof (UINT64)
1061 );
1062
1063 *UqiNode->Header.Value = (UINT8)StrToDec ((*argv)[0]);
1064 for (Index = 1; Index <= StrToDec ((*argv)[0]); Index++) {
1065 *((UINT64 *)UqiNode->Header.Value + Index) = StrToDec ((*argv)[Index]);
1066 }
1067 *argc -= (UINTN)StrToDec ((*argv)[0]);
1068 *argv += (UINTN)StrToDec ((*argv)[0]);
1069 break;
1070
1071 default:
1072 break;
1073 }
1074
1075 *argc -= 1;
1076 *argv += 1;
1077
1078 if (*argc > 0) {
1079 printf ("Error. The correct command is 'FCE updateq -i <infd> -o <outfd> <UQI> <Question Type> <Value>'.\n");
1080 return EFI_INVALID_PARAMETER;
1081 }
1082 return EFI_SUCCESS;
1083 }
1084 /**
1085 Parse the input Fd file, and get the file name according to the FILETYPE.
1086
1087 @param FdName The Name of Fd file
1088 @param FILETYPE The type of Fd file
1089
1090 @return EFI_SUCCESS Get the file name successfully
1091 @return EFI_ABORTED An error occurred.
1092 **/
1093 static
1094 EFI_STATUS
1095 ParseInFile (
1096 IN CHAR8 *FdName,
1097 IN FILETYPE Type
1098 )
1099 {
1100 FILE *Fptr;
1101
1102 Fptr = NULL;
1103
1104 if ((Type == INFD) && ((FdName == NULL) || (Fptr = fopen (FdName, "r")) == NULL)) {
1105 if (FdName != NULL) {
1106 printf ("Error: The <infd> file doesn't exist '%s'\n", FdName);
1107 }
1108 return EFI_ABORTED;
1109 }
1110 if ((Type == OUTFD) && (FdName == NULL) ) {
1111 printf ("Error: The <Outfd> name is NULL.\n");
1112 return EFI_ABORTED;
1113 }
1114 if ((Type == SETUPTXT) && (FdName == NULL) ) {
1115 printf ("Error: The <script> name is NULL.\n");
1116 return EFI_ABORTED;
1117 }
1118 if (strlen (FdName) > MAX_FILENAME_LEN - 1) {
1119 printf ("Error: The <fd> name is too long.\n");
1120 if (Fptr != NULL) {
1121 fclose (Fptr);
1122 }
1123 return EFI_ABORTED;
1124 }
1125 //
1126 // Get and copy the file name
1127 //
1128 if (Type == INFD) {
1129 strncpy (mInputFdName, FdName, MAX_FILENAME_LEN - 1);
1130 mInputFdName[MAX_FILENAME_LEN - 1] = 0;
1131 }
1132 if (Type == OUTFD) {
1133 strncpy (mOutputFdName, FdName, MAX_FILENAME_LEN - 1);
1134 mOutputFdName[MAX_FILENAME_LEN - 1] = 0;
1135 }
1136 if (Type == OUTTXT) {
1137 strncpy (mOutTxtName, FdName, MAX_FILENAME_LEN - 1);
1138 mOutTxtName[MAX_FILENAME_LEN - 1] = 0;
1139 }
1140 if (Type == SETUPTXT) {
1141 strncpy (mSetupTxtName, FdName, MAX_FILENAME_LEN - 1);
1142 mSetupTxtName[MAX_FILENAME_LEN - 1] = 0;
1143 }
1144 if (Fptr != NULL) {
1145 fclose (Fptr);
1146 }
1147 return EFI_SUCCESS;
1148 }
1149 /**
1150 Print the usage of this tools.
1151
1152 @return NULL
1153 **/
1154 static
1155 VOID
1156 Usage (
1157 VOID
1158 )
1159 {
1160 //
1161 // Print utility header
1162 //
1163 printf ("\nIntel(R) Firmware Configuration Editor. (Intel(R) %s) Version %d.%d. %s.\n\n",
1164 UTILITY_NAME,
1165 UTILITY_MAJOR_VERSION,
1166 UTILITY_MINOR_VERSION,
1167 __BUILD_VERSION
1168 );
1169 //
1170 // Copyright declaration
1171 //
1172 fprintf (stdout, "Copyright (c) 2010-2018, Intel Corporation. All rights reserved.\n\n");
1173 //
1174 // Summary usage
1175 //
1176 fprintf (stdout, "The tool enables you to retrieve and change HII configuration (Setup) data in \n");
1177 fprintf (stdout, "Firmware Device files.\n");
1178 fprintf (stdout, "\nUsage: \n");
1179 fprintf (stdout, " FCE [read -i <infd> [<PlatformId UQI>] ['>' <script>]] \n");
1180 fprintf (stdout, " FCE [update -i <infd> [<PlatformId UQI>|-s <script>] -o <outfd>\n");
1181 fprintf (stdout, " [--remove|--ignore] [-g <FvNameGuid>]] [-a]\n");
1182 fprintf (stdout, " FCE [verify -i <infd> -s <script>] \n");
1183 fprintf (stdout, " FCE [updateq -i <infd> -o <outfd> <UQI> <Question Type> <Value>] \n");
1184 fprintf (stdout, " FCE [[help] | [-?]] \n");
1185 fprintf (stdout, "\n");
1186
1187 fprintf (stdout, "Options:\n");
1188 fprintf (stdout, " read Extract the HII data from the <infd> file. \n");
1189 fprintf (stdout, " update Update the HII data to the <outfd> file. \n");
1190 fprintf (stdout, " verify Verify the current platform configuration. \n");
1191 fprintf (stdout, " updateq Update the current platform configuration by command line.\n");
1192 fprintf (stdout, " updateq only supports common mode.\n");
1193 fprintf (stdout, " help Display the help information.\n");
1194
1195 fprintf (stdout, " <infd> The name of a existing Firmware Device binary file input. \n");
1196 fprintf (stdout, " <PlatformId UQI> The UQI is required in multi-platform mode to represent a \n");
1197 fprintf (stdout, " PlatformId question from the VFR files used during binary \n");
1198 fprintf (stdout, " image creation. It must not be used for common mode. \n");
1199 fprintf (stdout, " <outfd> The name of a Firmware Device binary file output. \n");
1200 fprintf (stdout, " <script> The name of a configure scripts.\n");
1201 fprintf (stdout, " <UQI> A hex number followed by an array of hex numbers. \n");
1202 fprintf (stdout, " <Question Type> One of ORDERED_LIST, ONE_OF, NUMERIC, STRING or CHECKBOX. \n");
1203 fprintf (stdout, " <Value> A single hex number, if the <Question Type> is ONE_OF,\n");
1204 fprintf (stdout, " NUMERIC, or CHECKBOX. Or a single hex number containing \n");
1205 fprintf (stdout, " the array size followed by an array of that length of hex\n");
1206 fprintf (stdout, " numbers, if the <Question Type> is ORDERED_LIST. \n");
1207 fprintf (stdout, " <FvNameGuid> GuidValue is one specific FvName guid value.\n");
1208 fprintf (stdout, " Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.\n");
1209 fprintf (stdout, " -i Import an existing FD file <infd>. \n");
1210 fprintf (stdout, " -o Create the new FD with the changes made. \n");
1211 fprintf (stdout, " -s Import config scripts. \n");
1212 fprintf (stdout, " > Redirect the output to a scripts. \n");
1213 fprintf (stdout, " -? Display the help information. \n");
1214 fprintf (stdout, " --remove If one or more of the settings that are updated also \n");
1215 fprintf (stdout, " exists in NV RAM, remove them only in multi-platform mode.\n");
1216 fprintf (stdout, " --ignore If one or more of the settings that are updated also \n");
1217 fprintf (stdout, " existsin NV RAM, ignore them only in multi-platform mode.\n");
1218 fprintf (stdout, " -g Specify the FV image to store the multi-platform default \n");
1219 fprintf (stdout, " setting. If it is missing, the multi-platform default \n");
1220 fprintf (stdout, " will be inserted into BFV image.\n");
1221 fprintf (stdout, " -a Specify this tool to choose the smaller size between two \n");
1222 fprintf (stdout, " different storage formats in NV RAM. It's only vaild in \n");
1223 fprintf (stdout, " multi-platform mode. \n");
1224 fprintf (stdout, "\n");
1225
1226 fprintf (stdout, "Mode:\n");
1227 fprintf (stdout, " Common Extract the HII data from IFR binary and update it to the \n");
1228 fprintf (stdout, " EFI variable. \n");
1229 fprintf (stdout, " Multi-platform The default value depends on the PlatformId and DefaultId \n");
1230 fprintf (stdout, " described in the VFR files. This tool will create the \n");
1231 fprintf (stdout, " binary file to store default settings at build time for \n");
1232 fprintf (stdout, " different platforms and modes adding all default settings \n");
1233 fprintf (stdout, " into BFV as one FFS.\n");
1234
1235 fprintf (stdout, "\n");
1236 }
1237
1238 /**
1239 Parse the command line parameters
1240
1241 @param argc The pointer to number of input parameters.
1242 @param *argv[] The pointer to the parameters.
1243
1244 @retval EFI_SUCCESS Parse the parameters successfully.
1245 @retval EFI_INVALID_PARAMETER An error occurred.
1246
1247 **/
1248 static
1249 EFI_STATUS
1250 ParseCommmadLine (
1251 IN UINTN argc,
1252 IN CHAR8 *argv[]
1253 )
1254 {
1255 EFI_STATUS Status;
1256 UINT8 Index;
1257 UINT8 IndexParamI;
1258 UINT8 IndexParamS;
1259 UINT8 IndexParamO;
1260 UINT8 IndexParamRemove;
1261 UINT8 IndexParamIgnore;
1262 UINT8 IndexParamOptimize;
1263 EFI_GUID FvNameGuid;
1264
1265 Status = EFI_SUCCESS;
1266 Index = 0;
1267 IndexParamI = 0;
1268 IndexParamO = 0;
1269 IndexParamS = 0;
1270 IndexParamRemove = 0;
1271 IndexParamIgnore = 0;
1272 IndexParamOptimize = 0;
1273 mMultiPlatformParam.SizeOptimizedParam = FALSE;
1274 //
1275 // Check for only own one operations
1276 //
1277 if (argc == 0) {
1278 Usage ();
1279 Status = EFI_INVALID_PARAMETER;
1280 goto Done;
1281 }
1282 if (
1283 argc == 1 \
1284 && ((stricmp(argv[0], "read") == 0) \
1285 || (stricmp(argv[0], "update") == 0) \
1286 || (stricmp(argv[0], "updateq") == 0) \
1287 || (stricmp(argv[0], "verify") == 0) )
1288 ) {
1289 printf ("Error: Some parameters have been lost. Please correct. \n");
1290 Usage ();
1291 Status = EFI_INVALID_PARAMETER;
1292 goto Done;
1293 }
1294
1295 while (argc > 0) {
1296 if (stricmp(argv[0], "read") == 0) {
1297 Operations = READ;
1298 argc--;
1299 argv++;
1300
1301 if (argc < 2) {
1302 printf ("Error. The correct command is 'FCE read -i <infd>'. \n");
1303 Usage ();
1304 Status = EFI_INVALID_PARAMETER;
1305 goto Done;
1306 }
1307 //
1308 // Get input FD file name.
1309 //
1310 if (stricmp (argv[0], "-i") == 0) {
1311 Status = ParseInFile (argv[1], INFD);
1312 if (EFI_ERROR (Status)) {
1313 goto Done;
1314 }
1315 argc -= 2;
1316 argv += 2;
1317 }
1318 //
1319 // Parse the QUI parameters
1320 //
1321 if (argc > 2) {
1322 Status = ParseFirstpartOfUqi (&argv, &(mMultiPlatformParam.Uqi.HexNum), &(mMultiPlatformParam.Uqi.Data));
1323 mMultiPlatformParam.MultiPlatformOrNot = TRUE;
1324 if (EFI_ERROR (Status)) {
1325 goto Done;
1326 }
1327 }
1328 break;
1329
1330 } else if (stricmp(argv[0], "update") == 0) {
1331 //
1332 // Update the config file to Fd
1333 //
1334 Operations = UPDATE;
1335 argc--;
1336 argv++;
1337
1338 if (argc < 4) {
1339 printf ("Error. The correct command is 'FCE update -i <infd> [<PlatformId UQI>|-s <script>] -o <outfd>' \n");
1340 Usage ();
1341 Status = EFI_INVALID_PARAMETER;
1342 goto Done;
1343 }
1344
1345 continue;
1346 } else if (stricmp(argv[0], "verify") == 0) {
1347 //
1348 // 3. Parse the command line "FCE verify -i <infd> -s <script>"
1349 //
1350 Operations = VERIFY;
1351 argc--;
1352 argv++;
1353
1354 if (argc < 4) {
1355 printf ("Error. The correct command is 'FCE verify -i <infd> -s <script>'\n");
1356 Usage ();
1357 Status = EFI_INVALID_PARAMETER;
1358 goto Done;
1359 }
1360
1361 continue;
1362 } else if (stricmp(argv[0], "updateq") == 0) {
1363 //
1364 // Parse the command line "FCE updateq -i <infd> -o<outfd> <UQI> <Question Type> <Value>"
1365 //
1366 argc--;
1367 argv++;
1368
1369 //
1370 // Get input/output FD file name.
1371 //
1372 Index = 2;
1373 while ((Index > 0) && (argc > 1)) {
1374 if (stricmp (argv[0], "-i") == 0) {
1375 Status = ParseInFile (argv[1], INFD);
1376 if (EFI_ERROR (Status)) {
1377 goto Done;
1378 }
1379 argc -= 2;
1380 argv += 2;
1381 Index--;
1382 IndexParamI++;
1383 continue;
1384 }
1385
1386 if (stricmp (argv[0], "-o") == 0) {
1387 Status = ParseInFile (argv[1], OUTFD);
1388 if (EFI_ERROR (Status)) {
1389 goto Done;
1390 }
1391 argc -= 2;
1392 argv += 2;
1393 Index--;
1394 IndexParamO++;
1395 continue;
1396 }
1397 if (
1398 (argc >= 1) \
1399 && (stricmp(argv[0], "-o") != 0) \
1400 && (stricmp(argv[0], "-i") != 0)
1401 ) {
1402 printf ("Error. The correct command is 'FCE updateq -i <infd> -o <outfd> <UQI> <Question Type> <Value>' \n");
1403 Usage();
1404 Status = EFI_INVALID_PARAMETER;
1405 goto Done;
1406 }
1407 }
1408
1409 if (Index != 0) {
1410 printf ("Error. The correct command is 'FCE updateq -i <infd> -o <outfd> <UQI> <Question Type> <Value>' \n");
1411 Usage ();
1412 Status = EFI_INVALID_PARAMETER;
1413 goto Done;
1414 }
1415
1416 //
1417 // Parse the QUI parameters
1418 //
1419 Status = ParseUqiParam ((UINT32 *)&argc,&argv);
1420 if (EFI_ERROR (Status)) {
1421 goto Done;
1422 }
1423 Operations = UPDATEQ;
1424 break;
1425 }
1426
1427 if (stricmp (argv[0], "-i") == 0) {
1428 Status = ParseInFile (argv[1], INFD);
1429 if (EFI_ERROR (Status)) {
1430 goto Done;
1431 }
1432 argc -= 2;
1433 argv += 2;
1434 IndexParamI++;
1435 continue;
1436 }
1437
1438 if (stricmp (argv[0], "-o") == 0) {
1439 Status = ParseInFile (argv[1], OUTFD);
1440 if (EFI_ERROR (Status)) {
1441 goto Done;
1442 }
1443 argc -= 2;
1444 argv += 2;
1445 IndexParamO++;
1446 continue;
1447 }
1448
1449 if (stricmp (argv[0], "-s") == 0) {
1450 Status = ParseInFile (argv[1], SETUPTXT);
1451 if (EFI_ERROR (Status)) {
1452 goto Done;
1453 }
1454 argc -= 2;
1455 argv += 2;
1456 IndexParamS++;
1457 continue;
1458 }
1459
1460 if (stricmp (argv[0], "-g") == 0) {
1461 Status = StringToGuid (argv[1], &FvNameGuid);
1462 if (EFI_ERROR (Status)) {
1463 printf ("Error: Invalid parameters for -g option in command line. \n");
1464 Usage();
1465 goto Done;
1466 }
1467 mFvNameGuidString = argv[1];
1468 argc -= 2;
1469 argv += 2;
1470 continue;
1471 }
1472
1473 if (stricmp (argv[0], "-a") == 0) {
1474 argc -= 1;
1475 argv += 1;
1476 IndexParamOptimize++;
1477 mMultiPlatformParam.SizeOptimizedParam = TRUE;
1478 continue;
1479 }
1480
1481 if (stricmp (argv[0], "--remove") == 0) {
1482 argc -= 1;
1483 argv += 1;
1484 IndexParamRemove++;
1485 Operations = UPDATE_REMOVE;
1486 continue;
1487 }
1488
1489 if (stricmp (argv[0], "--ignore") == 0) {
1490 argc -= 1;
1491 argv += 1;
1492 IndexParamIgnore++;
1493 Operations = UPDATE_IGNORE;
1494 continue;
1495 }
1496
1497 if ((stricmp(argv[0], "help") == 0) || (stricmp(argv[0], "-?") == 0)) {
1498
1499 Usage();
1500 Status = EFI_INVALID_PARAMETER;
1501 goto Done;
1502 }
1503 //
1504 // Operations should not be none
1505 //
1506 if ( Operations == NONE ) {
1507 printf ("Error. Only support read/update/verify/updateq mode. \n");
1508 Usage();
1509 Status = EFI_INVALID_PARAMETER;
1510 goto Done;
1511 }
1512
1513 if (Operations == UPDATE) {
1514 Status = ParseFirstpartOfUqi (&argv, &(mMultiPlatformParam.Uqi.HexNum), &(mMultiPlatformParam.Uqi.Data));
1515 if (!EFI_ERROR (Status)) {
1516 mMultiPlatformParam.MultiPlatformOrNot = TRUE;
1517 argc = argc - mMultiPlatformParam.Uqi.HexNum - 1;
1518 argv = argv + mMultiPlatformParam.Uqi.HexNum + 1;
1519 continue;
1520 }
1521 }
1522
1523 if (
1524 (argc >= 1) \
1525 && (stricmp(argv[0], "-?") != 0)
1526 && (stricmp(argv[0], "help") != 0)
1527 && (stricmp(argv[0], "verify") != 0)
1528 && (stricmp(argv[0], "read") != 0)
1529 && (stricmp(argv[0], "update") != 0)
1530 && (stricmp(argv[0], "updateq") != 0)
1531 && (stricmp(argv[0], "-o") != 0)
1532 && (stricmp(argv[0], "-i") != 0)
1533 && (stricmp(argv[0], "-s") != 0)
1534 && (stricmp(argv[0], "-a") != 0)
1535 && (stricmp(argv[0], "-g") != 0)
1536 && (stricmp(argv[0], "--remove") != 0)
1537 && (stricmp(argv[0], "--ignore") != 0)
1538 ) {
1539 printf ("Error: Invalid parameters exist in command line. \n");
1540 Usage();
1541 Status = EFI_INVALID_PARAMETER;
1542 goto Done;
1543 }
1544 }
1545 //
1546 // Check the repeated parameters in command line, such as "-i -i"
1547 //
1548 if (
1549 (IndexParamI > 1)
1550 || (IndexParamO > 1)
1551 || (IndexParamS > 1)
1552 || (IndexParamOptimize > 1)
1553 || (IndexParamRemove > 1)
1554 || (IndexParamIgnore > 1)
1555 ) {
1556 printf ("Error: Redundant parameters exist in command line.\n");
1557 Usage();
1558 Status = EFI_INVALID_PARAMETER;
1559 goto Done;
1560 }
1561 //
1562 // Check improper parameters in command line, such as "FCE read -i -s"
1563 //
1564 if (
1565 ((Operations == READ) && ((IndexParamO >= 1) || (IndexParamS >= 1) || (IndexParamRemove >= 1) || (IndexParamIgnore >= 1))) \
1566 || ((Operations == VERIFY) && ((IndexParamO >= 1) || (IndexParamRemove >= 1) || (IndexParamIgnore >= 1))) \
1567 || ((Operations == UPDATEQ) && ((IndexParamS >= 1) || (IndexParamRemove >= 1) || (IndexParamIgnore >= 1))) \
1568 || ((Operations == UPDATE) && ((IndexParamRemove >= 1) && (IndexParamIgnore >= 1)))
1569 || ((Operations != UPDATE && Operations != UPDATE_REMOVE && Operations != UPDATE_IGNORE) && ((IndexParamOptimize >= 1) || (mFvNameGuidString != NULL)))
1570 ) {
1571 printf ("Error: Improper parameters exist in command line. \n");
1572 Usage();
1573 Status = EFI_INVALID_PARAMETER;
1574 goto Done;
1575 }
1576 Done:
1577 return Status;
1578 }
1579
1580 /**
1581 Check whether exists the valid variables in NvStorage or not.
1582
1583 @retval TRUE If existed, return TRUE.
1584 @retval FALSE Others
1585 **/
1586 static
1587 BOOLEAN
1588 ExistEfiVarOrNot (
1589 IN LIST_ENTRY *StorageListHead
1590 )
1591 {
1592 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
1593 BOOLEAN Existed;
1594 VOID *VariableStoreHeader;
1595 BOOLEAN AuthencitatedMonotonicOrNot;
1596 BOOLEAN AuthencitatedBasedTimeOrNot;
1597
1598 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
1599 VariableStoreHeader = (VOID *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
1600 AuthencitatedMonotonicOrNot = FALSE;
1601 AuthencitatedBasedTimeOrNot = FALSE;
1602 Existed = TRUE;
1603 //
1604 // Judge the layout of NV by gEfiVariableGuid
1605 //
1606 AuthencitatedMonotonicOrNot = CheckMonotonicBasedVarStore (VariableStoreHeader);
1607 AuthencitatedBasedTimeOrNot = CheckTimeBasedVarStoreOrNot (VariableStoreHeader);
1608
1609 if (AuthencitatedMonotonicOrNot) {
1610 //
1611 // Check the Monotonic based authenticate variable
1612 //
1613 Existed = ExistMonotonicBasedEfiVarOrNot (StorageListHead);
1614 } else if (AuthencitatedBasedTimeOrNot){
1615 //
1616 // Check the Time Sample authenticate variable
1617 //
1618 Existed = ExistTimeBasedEfiVarOrNot (StorageListHead);
1619 } else {
1620 //
1621 // Check the normal variable
1622 //
1623 Existed = ExistNormalEfiVarOrNot (StorageListHead);
1624 }
1625
1626 return Existed;
1627 }
1628
1629 /**
1630 Exchange the data between Efi variable and the data of VarList
1631
1632 If VarToList is TRUE, copy the efi variable data to the VarList; Otherwise,
1633 update the data from varlist to efi variable.
1634
1635 @param VarToList The flag to control the direction of exchange.
1636 @param StorageListHead Decide which variale list be updated
1637
1638 @retval EFI_SUCCESS Get the address successfully.
1639 **/
1640 static
1641 EFI_STATUS
1642 EfiVarAndListExchange (
1643 IN BOOLEAN VarToList,
1644 IN LIST_ENTRY *StorageListHead
1645 )
1646 {
1647 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
1648 EFI_STATUS Status;
1649 VOID *VariableStoreHeader;
1650 BOOLEAN AuthencitatedMonotonicOrNot;
1651 BOOLEAN AuthencitatedBasedTimeOrNot;
1652
1653 Status = EFI_ABORTED;
1654 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
1655 VariableStoreHeader = (VOID *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
1656 AuthencitatedMonotonicOrNot = FALSE;
1657 AuthencitatedBasedTimeOrNot = FALSE;
1658 //
1659 // Judge the layout of NV by gEfiVariableGuid
1660 //
1661 AuthencitatedMonotonicOrNot = CheckMonotonicBasedVarStore (VariableStoreHeader);
1662 AuthencitatedBasedTimeOrNot = CheckTimeBasedVarStoreOrNot (VariableStoreHeader);
1663
1664 if (AuthencitatedMonotonicOrNot) {
1665 //
1666 // Update the Monotonic based authenticate variable
1667 //
1668 Status = SynAuthEfiVariable (VarToList, StorageListHead);
1669 } else if (AuthencitatedBasedTimeOrNot){
1670 //
1671 // Update the Time Sample authenticate variable
1672 //
1673 Status = SynAuthEfiVariableBasedTime (VarToList, StorageListHead);
1674 } else {
1675 //
1676 // Update the normal variable
1677 //
1678 Status = SynEfiVariable (VarToList, StorageListHead);
1679 }
1680
1681 return Status;
1682 }
1683
1684 /**
1685 Check the layout of NvStorage and remove the variable from Efi variable
1686
1687 Found the variable with the same name in StorageListHead and remove it.
1688
1689 @param StorageListHead Decide which variale list be removed.
1690
1691 @retval EFI_SUCCESS Remove the variables successfully.
1692 **/
1693 static
1694 EFI_STATUS
1695 RemoveEfiVar (
1696 IN LIST_ENTRY *StorageListHead
1697 )
1698 {
1699 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
1700 EFI_STATUS Status;
1701 VOID *VariableStoreHeader;
1702 BOOLEAN AuthencitatedMonotonicOrNot;
1703 BOOLEAN AuthencitatedBasedTimeOrNot;
1704
1705 Status = EFI_ABORTED;
1706 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
1707 VariableStoreHeader = (VOID *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
1708 AuthencitatedMonotonicOrNot = FALSE;
1709 AuthencitatedBasedTimeOrNot = FALSE;
1710 //
1711 // Judge the layout of NV by gEfiVariableGuid
1712 //
1713 AuthencitatedMonotonicOrNot = CheckMonotonicBasedVarStore (VariableStoreHeader);
1714 AuthencitatedBasedTimeOrNot = CheckTimeBasedVarStoreOrNot (VariableStoreHeader);
1715
1716 if (AuthencitatedMonotonicOrNot) {
1717 //
1718 // Update the Monotonic based authenticate variable
1719 //
1720 Status = RemoveAuthEfiVariable (StorageListHead);
1721 } else if (AuthencitatedBasedTimeOrNot){
1722 //
1723 // Update the Time Sample authenticate variable
1724 //
1725 Status = RemoveAuthEfiVariableBasedTime (StorageListHead);
1726 } else {
1727 //
1728 // Update the normal variable
1729 //
1730 Status = RemoveNormalEfiVariable (StorageListHead);
1731 }
1732
1733 return Status;
1734 }
1735
1736 /**
1737 Parse the all formset in one VfrBin.
1738
1739 Parse all questions, variables and expression in VfrBin, and store
1740 it in Formset and Form.
1741
1742 @param BaseAddr The pointer to the array of VfrBin base address.
1743 @param UniBinBaseAddress The pointer to one Uni string base address.
1744
1745 @retval EFI_SUCCESS The Search was complete successfully
1746 @return EFI_ABORTED An error occurred
1747 **/
1748 static
1749 EFI_STATUS
1750 ParseFormSetInVfrBin (
1751 IN UINTN **BaseAddr,
1752 IN UINTN *UniBinBaseAddress,
1753 IN UINT8 Index
1754 )
1755 {
1756 UINT32 PackageLength;
1757 EFI_STATUS Status;
1758 FORM_BROWSER_FORMSET *FormSet;
1759 UINT8 *IfrBinaryData;
1760 EFI_IFR_OP_HEADER *IfrOpHdr;
1761 UINT32 IfrOffset;
1762
1763 PackageLength = 0;
1764 Status = EFI_SUCCESS;
1765 FormSet = NULL;
1766 IfrBinaryData = NULL;
1767 IfrOpHdr = NULL;
1768
1769 //
1770 // The first 4 Bytes of VfrBin is used to record the Array Length
1771 // The header of VfrBin is, ARRAY LENGTH:4 Bytes, PACKAGE HEADER:4 Bytes (2 Bytes for Len, and the other for Type)
1772 //
1773 PackageLength = *(UINT32 *)*(BaseAddr + Index) - 4;
1774 IfrBinaryData = (UINT8 *)*(BaseAddr + Index) + 4;
1775
1776 //
1777 // Go through the form package to parse OpCode one by one.
1778 //
1779 IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
1780
1781 while (IfrOffset < PackageLength) {
1782 //
1783 // Search the Formset in VfrBin
1784 //
1785 IfrOpHdr = (EFI_IFR_OP_HEADER *) (IfrBinaryData + IfrOffset);
1786
1787 if (IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) {
1788 FormSet = calloc (sizeof (FORM_BROWSER_FORMSET), sizeof (CHAR8));
1789 if (FormSet == NULL) {
1790 return EFI_ABORTED;
1791 }
1792 FormSet->IfrBinaryData = IfrBinaryData + IfrOffset;
1793 FormSet->UnicodeBinary = (UINT8 *) UniBinBaseAddress;
1794 //
1795 //This length will be corrected in ParseOpCodes function.
1796 //
1797 FormSet->IfrBinaryLength = PackageLength - IfrOffset;
1798 //
1799 // Parse opcodes in the formset IFR binary.
1800 //
1801 Status = ParseOpCodes (FormSet);
1802 if (EFI_ERROR (Status)) {
1803 DestroyAllStorage (FormSet->StorageListHead);
1804 DestroyFormSet (FormSet);
1805 return EFI_ABORTED;
1806 }
1807 IfrOffset += FormSet->IfrBinaryLength;
1808 FormSet->EnUsStringList.StringInfoList = calloc (sizeof (STRING_INFO), STRING_NUMBER);
1809 FormSet->EnUsStringList.CachedIdNum = 0;
1810 FormSet->EnUsStringList.MaxIdNum = STRING_NUMBER;
1811 FormSet->UqiStringList.StringInfoList = calloc (sizeof (STRING_INFO), STRING_NUMBER);
1812 FormSet->UqiStringList.CachedIdNum = 0;
1813 FormSet->UqiStringList.MaxIdNum = STRING_NUMBER;
1814 //
1815 // Insert the FormSet to mFormSet
1816 //
1817 InsertTailList (&mFormSetListEntry, &FormSet->Link);
1818 } else {
1819 IfrOffset += IfrOpHdr->Length;
1820 }
1821 }
1822
1823 return EFI_SUCCESS;
1824 }
1825
1826 /**
1827 Store all defaultId to mMultiPlatformParam.
1828
1829 The mMultiPlatformParam.DefaultId[0] is used to store standard default.
1830
1831 @param DefaultId The current defaultID.
1832
1833 @retval EFI_SUCCESS It was complete successfully
1834 @return EFI_ABORTED An error occurred
1835 **/
1836 VOID
1837 StoreAllDefaultId (
1838 IN UINT16 DefaultId
1839 )
1840 {
1841 UINT32 Index;
1842
1843 if ((mMultiPlatformParam.DefaultIdNum == 0) && (DefaultId != 0)) {
1844 mMultiPlatformParam.DefaultId[0] = DefaultId;
1845 mMultiPlatformParam.DefaultIdNum++;
1846 return;
1847 }
1848 //
1849 // Only store the different value to mMultiPlatformParam.DefaultId[1] - mMultiPlatformParam.DefaultId[n]
1850 //
1851 for (Index = 0; Index < mMultiPlatformParam.DefaultIdNum; Index++) {
1852 if (mMultiPlatformParam.DefaultId[Index] == DefaultId) {
1853 return;
1854 }
1855 }
1856 mMultiPlatformParam.DefaultId[Index] = DefaultId;
1857 mMultiPlatformParam.DefaultIdNum++;
1858 }
1859
1860 /**
1861 Read all defaultId and platformId from binary.
1862
1863 @param Binary The pointer to the bianry
1864 @param Storage The pointer to the Storage
1865 **/
1866 VOID
1867 ReadDefaultAndPlatformIdFromBfv (
1868 IN UINT8 *Binary,
1869 IN FORMSET_STORAGE *Storage
1870 )
1871 {
1872 UINT16 Length;
1873 UINT16 Size;
1874 UINT32 Index;
1875
1876 Length = *(UINT16 *)Binary - sizeof (UINT16);
1877 Index = 0;
1878 Size = 0;
1879
1880 Binary = Binary + sizeof (UINT16);
1881
1882 for (Size = 0; Size < Length; Size += sizeof (UINT16) + mMultiPlatformParam.PlatformIdWidth, Index++) {
1883 Storage->DefaultId[Index] = *(UINT16 *)(Binary + Size);
1884 memcpy (&Storage->PlatformId[Index], (Binary + Size + sizeof (UINT16)), mMultiPlatformParam.PlatformIdWidth);
1885 }
1886 Storage->DefaultPlatformIdNum = Index - 1;
1887 }
1888
1889 /**
1890 Store all defaultId and platformId to binary.
1891
1892 @param Binary The pointer to the bianry
1893 @param Storage The pointer to the Storage
1894
1895 @retval Length Return the length of the header
1896 **/
1897 UINT32
1898 WriteDefaultAndPlatformId (
1899 IN UINT8 *Binary,
1900 IN FORMSET_STORAGE *Storage
1901 )
1902 {
1903 UINT16 Length;
1904 UINT32 Index;
1905 UINT8 *Buffer;
1906
1907 Length = 0;
1908 Buffer = Binary;
1909
1910 Buffer = Buffer + sizeof (CHAR16);
1911
1912 for (Index = 0; Index <= Storage->DefaultPlatformIdNum; Index++) {
1913 *(UINT16 *)Buffer = Storage->DefaultId[Index];
1914 Buffer = Buffer + sizeof (CHAR16);
1915 memcpy (Buffer, &Storage->PlatformId[Index], mMultiPlatformParam.PlatformIdWidth);
1916 Buffer = Buffer + mMultiPlatformParam.PlatformIdWidth;
1917 }
1918 Length = (UINT16) (Buffer - Binary);
1919 //
1920 // Record the offset to the first two bytes
1921 //
1922 *(UINT16 *)Binary = Length;
1923
1924 return Length;
1925 }
1926
1927 /**
1928 Store all defaultId and platformId to binary.
1929
1930 @param Binary The pointer to the bianry
1931 @param Storage The pointer to the Storage
1932
1933 @retval Length Return the length of the header
1934 **/
1935 UINT32
1936 WriteNvStoreDefaultAndPlatformId (
1937 IN UINT8 *Binary,
1938 IN FORMSET_STORAGE *Storage
1939 )
1940 {
1941 UINT16 Length;
1942 UINT32 Index;
1943 UINT8 *Buffer;
1944
1945 Length = 0;
1946 Buffer = Binary + 8;
1947
1948 for (Index = 0; Index <= Storage->DefaultPlatformIdNum; Index++) {
1949 *(UINT64 *)Buffer = Storage->PlatformId[Index];
1950 Buffer = Buffer + sizeof(UINT64);
1951 *(UINT16 *)Buffer = Storage->DefaultId[Index];
1952 Buffer = Buffer + sizeof(UINT16);
1953 // for Resered
1954 Buffer = Buffer + 6;
1955 }
1956 Length = (UINT16) (Buffer - Binary - 8);
1957 // for Header size
1958 Length += 4;
1959 return Length;
1960 }
1961
1962 /**
1963 Read the platformId from questions.
1964
1965 @retval EFI_SUCCESS It was complete successfully.
1966 @return EFI_ABORTED An error occurred.
1967 **/
1968 EFI_STATUS
1969 ReadPlaformId (
1970 IN FORM_BROWSER_STATEMENT *CurQuestion
1971 )
1972 {
1973 UINT16 Index;
1974 UINT64 IdValue;
1975 LIST_ENTRY *Link;
1976 QUESTION_OPTION *Option;
1977 UINT64 Step;
1978
1979 Index = 0;
1980 IdValue = 0;
1981 Step = 0;
1982 //
1983 // Check whether it is the question of paltform Id
1984 //
1985 if (!CompareUqiHeader (&(CurQuestion->Uqi), &(mMultiPlatformParam.Uqi))) {
1986 return EFI_ABORTED;
1987 }
1988 //
1989 // Copy the Question with platform to mMultiPlatformParam
1990 //
1991 memcpy (&mMultiPlatformParam.PlatformIdQuestion, CurQuestion, sizeof (FORM_BROWSER_STATEMENT));
1992 mMultiPlatformParam.Question = CurQuestion;
1993 //
1994 // Pick up the value of NUMERIC and ONE_OF from current question and fill it in mMultiPlatformParam
1995 //
1996 mMultiPlatformParam.PlatformIdWidth = CurQuestion->StorageWidth;
1997
1998 if (CurQuestion->Operand == EFI_IFR_NUMERIC_OP) {
1999 Index = 0;
2000 if (CurQuestion->Step == 0) {
2001 Step = 1;
2002 } else {
2003 Step = CurQuestion->Step;
2004 }
2005 for (IdValue = CurQuestion->Minimum; IdValue < CurQuestion->Maximum; IdValue += Step) {
2006 mMultiPlatformParam.PlatformId[Index++] = (UINT64)IdValue;
2007 }
2008 }
2009
2010 if (CurQuestion->Operand == EFI_IFR_ONE_OF_OP) {
2011 Index = 0;
2012
2013 Link = GetFirstNode (&CurQuestion->OptionListHead);
2014 while (!IsNull (&CurQuestion->OptionListHead, Link)) {
2015 Option = QUESTION_OPTION_FROM_LINK (Link);
2016 mMultiPlatformParam.PlatformId[Index++] = Option->Value.Value.u64;
2017 Link = GetNextNode (&CurQuestion->OptionListHead, Link);
2018 }
2019 }
2020
2021 if (Index >= MAX_PLATFORM_DEFAULT_ID_NUM) {
2022 return EFI_ABORTED;
2023 }
2024 mMultiPlatformParam.PlatformIdNum = Index;
2025
2026 return EFI_SUCCESS;
2027 }
2028
2029 /**
2030 Clear the buffer of Storage list.
2031
2032 @param StorageListHead The pointer to the entry of the storage list
2033 @param DefaultId The default Id for multi-platform support
2034 @param PlatformId The platform Id for multi-platform support
2035
2036 @retval NULL
2037 **/
2038 VOID
2039 ClearStorageEntryList (
2040 IN LIST_ENTRY *StorageListHead,
2041 IN UINT16 DefaultId,
2042 IN UINT64 PlatformId
2043 )
2044 {
2045
2046 LIST_ENTRY *StorageLink;
2047 FORMSET_STORAGE *Storage;
2048
2049 Storage = NULL;
2050
2051 StorageLink = GetFirstNode (StorageListHead);
2052
2053 while (!IsNull (StorageListHead, StorageLink)) {
2054 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
2055 if (Storage != NULL) {
2056 memset (Storage->Buffer, 0x0, Storage->Size);
2057 Storage->DefaultId[0] = DefaultId;
2058 Storage->PlatformId[0] = PlatformId;
2059 Storage->DefaultPlatformIdNum = 0;
2060 }
2061 StorageLink = GetNextNode (StorageListHead, StorageLink);
2062 }
2063 }
2064
2065 /**
2066 Append the platformid and default to the variables of CurDefaultId and CurPlatformId
2067
2068 @param StorageListHead The pointer to the storage list
2069 @param CurDefaultId The default Id for multi-platform mode
2070 @param CurPlatformId The platform Id for multi-platform mode
2071 @param DefaultId The default Id for multi-platform mode
2072 @param PlatformId The platform Id for multi-platform mode
2073
2074 @retval NULL
2075 **/
2076 VOID
2077 AppendIdToVariables (
2078 IN LIST_ENTRY *StorageListHead,
2079 IN UINT16 CurDefaultId,
2080 IN UINT64 CurPlatformId,
2081 IN UINT16 DefaultId,
2082 IN UINT64 PlatformId
2083 )
2084 {
2085 LIST_ENTRY *StorageLink;
2086 FORMSET_STORAGE *Storage;
2087
2088 Storage = NULL;
2089
2090 StorageLink = GetFirstNode (StorageListHead);
2091
2092 while (!IsNull (StorageListHead, StorageLink)) {
2093 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
2094
2095 if ((Storage->DefaultId[0] == CurDefaultId)
2096 && (Storage->PlatformId[0] == CurPlatformId)
2097 ) {
2098 ++Storage->DefaultPlatformIdNum;
2099 Storage->DefaultId[Storage->DefaultPlatformIdNum] = DefaultId;
2100 Storage->PlatformId[Storage->DefaultPlatformIdNum] = PlatformId;
2101 }
2102
2103 StorageLink = GetNextNode (StorageListHead, StorageLink);
2104 }
2105 }
2106
2107
2108 /**
2109 Check whether StorageListHead2 is included in StorageListHead1
2110
2111 @param StorageListHead1 The pointer to the entry of storage list
2112 @param StorageListHead2 The pointer to the entry of storage list
2113 @param DefaultId The default Id for multi-platform mode
2114 @param PlatformId The platform Id for multi-platform mode
2115
2116 @retval TRUE Totally included.
2117 @return FALSE Other cases.
2118 **/
2119 BOOLEAN
2120 ComparePartSameVariableList (
2121 IN LIST_ENTRY *StorageListHead1,
2122 IN LIST_ENTRY *StorageListHead2,
2123 OUT UINT16 *DefaultId,
2124 OUT UINT64 *PlatformId
2125 )
2126 {
2127 LIST_ENTRY *StorageLink;
2128 LIST_ENTRY *TempStorageHead;
2129 LIST_ENTRY *TempStorageLink;
2130 LIST_ENTRY *TempStorageHead2;
2131 LIST_ENTRY *TempStorageLink2;
2132 FORMSET_STORAGE *Storage;
2133 FORMSET_STORAGE *TempStorage;
2134 FORMSET_STORAGE *TempStorage2;
2135 UINT16 CurDefaultId;
2136 UINT64 CurPlatformId;
2137 UINT32 VariableNum;
2138 UINT32 Index;
2139
2140 StorageLink = NULL;
2141 TempStorageHead = NULL;
2142 TempStorageLink = NULL;
2143 TempStorageHead2 = NULL;
2144 TempStorageLink2 = NULL;
2145 Storage = NULL;
2146 TempStorage = NULL;
2147 TempStorage2 = NULL;
2148 CurDefaultId = 0;
2149 CurPlatformId = 0;
2150 VariableNum = 0;
2151 Index = 0;
2152 TempStorageHead = StorageListHead1;
2153
2154
2155 //
2156 // Get the number of variables in StorageListHead2;
2157 //
2158 StorageLink = GetFirstNode (StorageListHead2);
2159
2160 while (!IsNull (StorageListHead2, StorageLink)) {
2161 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
2162 //
2163 // For multi-platform support, only need to calcuate the type of EFI_IFR_VARSTORE_EFI_OP.
2164 //
2165 if (mMultiPlatformParam.MultiPlatformOrNot &&
2166 (Storage->Type == EFI_IFR_VARSTORE_EFI_OP) && (Storage->Name != NULL) && (Storage->NewEfiVarstore) &&
2167 ((Storage->Attributes & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE)) {
2168 VariableNum++;
2169 }
2170 StorageLink = GetNextNode (StorageListHead2, StorageLink);
2171 }
2172 //
2173 // Parse every variables in StorageListHead1 and compare with ones in StorageListHead2
2174 // Only all variables in StorageListHead2 are included in StorageListHead1, return TRUE.
2175 //
2176 StorageLink = GetFirstNode (StorageListHead1);
2177
2178 while (!IsNull (StorageListHead1, StorageLink)) {
2179 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
2180 //
2181 // Get specified DefaultId and PlatformId firstly
2182 //
2183 CurDefaultId = Storage->DefaultId[0];
2184 CurPlatformId = Storage->PlatformId[0];
2185 Index = 0;
2186 //
2187 // Compare all variables under same defaultId and platformId
2188 //
2189 TempStorageLink = GetFirstNode (TempStorageHead);
2190 while (!IsNull (TempStorageHead, TempStorageLink)) {
2191 TempStorage = FORMSET_STORAGE_FROM_LINK (TempStorageLink);
2192 if ((TempStorage->DefaultId[0] == CurDefaultId)
2193 && (TempStorage->PlatformId[0] == CurPlatformId)
2194 && (TempStorage->Name != NULL)
2195 && (TempStorage->Type == EFI_IFR_VARSTORE_EFI_OP)
2196 && (TempStorage->NewEfiVarstore)
2197 && ((TempStorage->Attributes & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE)
2198 ) {
2199 //
2200 //Search the matched variable by Guid and name in StorageListHead2
2201 //
2202 TempStorageHead2 = StorageListHead2;
2203 TempStorageLink2 = GetFirstNode (TempStorageHead2);
2204
2205 while (!IsNull (TempStorageHead2, TempStorageLink2)) {
2206 TempStorage2 = FORMSET_STORAGE_FROM_LINK (TempStorageLink2);
2207 if ((TempStorage2->Name != NULL)
2208 && (TempStorage2->Type == EFI_IFR_VARSTORE_EFI_OP)
2209 && (TempStorage2->NewEfiVarstore)
2210 && ((TempStorage2->Attributes & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE)
2211 && !FceStrCmp (TempStorage->Name, TempStorage2->Name)
2212 && !CompareGuid(&TempStorage->Guid, &TempStorage2->Guid)
2213 ) {
2214 if (CompareMem (TempStorage->Buffer, TempStorage2->Buffer, TempStorage->Size) == 0) {
2215 Index++;
2216 }
2217 }
2218 TempStorageLink2 = GetNextNode (TempStorageHead2, TempStorageLink2);
2219 }
2220 }
2221 TempStorageLink = GetNextNode (TempStorageHead, TempStorageLink);
2222 }
2223 //
2224 // Check the matched variable number
2225 //
2226 if (Index == VariableNum) {
2227 *DefaultId = CurDefaultId;
2228 *PlatformId = CurPlatformId;
2229 return TRUE;
2230 }
2231 StorageLink = GetNextNode (StorageListHead1, StorageLink);
2232 }
2233 return FALSE;
2234 }
2235
2236 /**
2237 Check whether the defaultId and platformId mathched the variable or not
2238
2239 @param Storage The pointer to the storage
2240 @param DefaultId The default Id for multi-platform mode
2241 @param PlatformId The platform Id for multi-platform mode
2242
2243 @retval TRUE Not Matched.
2244 @return FALSE Matched any one
2245 **/
2246 BOOLEAN
2247 NotEqualAnyIdOfStorage (
2248 IN FORMSET_STORAGE *Storage,
2249 IN UINT16 DefaultId,
2250 IN UINT64 PlatformId
2251 )
2252 {
2253 UINT32 Index;
2254
2255 for (Index = 0; Index <= Storage->DefaultPlatformIdNum; Index++) {
2256 if ((Storage->DefaultId[Index] == DefaultId)
2257 &&(Storage->PlatformId[Index] == PlatformId)
2258 ) {
2259 return FALSE;
2260 }
2261 }
2262 return TRUE;
2263 }
2264
2265 /**
2266 Copy Stroage from StorageListHead2 to StorageListHead1
2267
2268 @param NewStorageListHead The pointer to the entry of storage list
2269 @param OldStorageListHead The pointer to the entry of storage list
2270 @param DefaultId The default Id for multi-platform mode
2271 @param PlatformId The platform Id for multi-platform mode
2272 @param AssignIdOrNot If True, assign the platform Id and default Id to storage;
2273 Or else, only copy the variables under the specified platform
2274 Id and default to the other list.
2275 @param Mode The operation of mode
2276
2277 @retval EFI_SUCCESS It was complete successfully
2278 @return EFI_ABORTED An error occurred
2279 **/
2280 EFI_STATUS
2281 BuildVariableList (
2282 IN LIST_ENTRY *NewStorageListHead,
2283 IN LIST_ENTRY *OldStorageListHead,
2284 IN UINT16 DefaultId,
2285 IN UINT64 PlatformId,
2286 IN BOOLEAN AssignIdOrNot,
2287 IN OPERATION_TYPE Mode
2288 )
2289 {
2290 LIST_ENTRY *StorageLink;
2291 LIST_ENTRY *NameValueLink;
2292 FORMSET_STORAGE *Storage;
2293 FORMSET_STORAGE *StorageCopy;
2294 IN LIST_ENTRY *StorageListHead1;
2295 IN LIST_ENTRY *StorageListHead2;
2296 NAME_VALUE_NODE *NameValueNode;
2297 NAME_VALUE_NODE *CopyNameValueNode;
2298
2299 Storage = NULL;
2300 NameValueNode = NULL;
2301 StorageListHead1 = NewStorageListHead;
2302 StorageListHead2 = OldStorageListHead;
2303
2304 StorageLink = GetFirstNode (StorageListHead2);
2305
2306 while (!IsNull (StorageListHead2, StorageLink)) {
2307 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
2308
2309 if ((Storage->Type == EFI_IFR_VARSTORE_EFI_OP)
2310 ||(Storage->Type == EFI_IFR_VARSTORE_OP)
2311 ) {
2312 //
2313 // Only support EfiVarStore in Multi-Platform mode, and the attribute must be EFI_VARIABLE_NON_VOLATILE
2314 //
2315 if (mMultiPlatformParam.MultiPlatformOrNot) {
2316 if (Storage->Type == EFI_IFR_VARSTORE_OP) {
2317 StorageLink = GetNextNode (StorageListHead2, StorageLink);
2318 continue;
2319 }
2320 if ((Storage->Type == EFI_IFR_VARSTORE_EFI_OP)
2321 && Storage->NewEfiVarstore
2322 && ((Storage->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)
2323 ) {
2324 StorageLink = GetNextNode (StorageListHead2, StorageLink);
2325 continue;
2326 }
2327 if (AssignIdOrNot) {
2328 Storage->DefaultId[0] = DefaultId;
2329 Storage->PlatformId[0] = PlatformId;
2330 } else {
2331 //
2332 //only copy the variables under the specified platform Id and default to the other list.
2333 //
2334 if ((Mode == VERIFY) && (NotEqualAnyIdOfStorage (Storage, DefaultId, PlatformId))) {
2335 StorageLink = GetNextNode (StorageListHead2, StorageLink);
2336 continue;
2337 } else if ((Mode != VERIFY) && (Storage->DefaultId[0] != DefaultId || Storage->PlatformId[0] != PlatformId) ) {
2338 StorageLink = GetNextNode (StorageListHead2, StorageLink);
2339 continue;
2340 }
2341 }
2342 }
2343 //
2344 // Copy Storage Node
2345 //
2346 if (Storage->Name == NULL) {
2347 return EFI_ABORTED;
2348 }
2349 StorageCopy = NULL;
2350 StorageCopy = calloc (sizeof (FORMSET_STORAGE), sizeof (CHAR8));
2351 if (StorageCopy == NULL) {
2352 printf ("Memory allocation failed.\n");
2353 return EFI_ABORTED;
2354 }
2355 memcpy (StorageCopy, Storage, sizeof (FORMSET_STORAGE));
2356
2357 if (Mode == VERIFY) {
2358 StorageCopy->DefaultId[0] = DefaultId;
2359 StorageCopy->PlatformId[0] = PlatformId;
2360 }
2361 //
2362 //Set the flags for sorting out the variables
2363 //
2364 StorageCopy->Skip = FALSE;
2365
2366 StorageCopy->Name = NULL;
2367 StorageCopy->Name = calloc (FceStrLen (Storage->Name) + 1, sizeof (CHAR16));
2368 if (StorageCopy->Name == NULL) {
2369 printf ("Memory allocation failed.\n");
2370 free (StorageCopy);
2371 return EFI_ABORTED;
2372 }
2373 StrCpy (StorageCopy->Name, Storage->Name);
2374
2375 StorageCopy->Buffer = NULL;
2376 StorageCopy->Buffer = calloc (Storage->Size, sizeof (CHAR8));
2377 if (StorageCopy->Buffer == NULL) {
2378 free (StorageCopy->Name);
2379 free (StorageCopy);
2380 printf ("Memory allocation failed.\n");
2381 return EFI_ABORTED;
2382 }
2383 CopyMem (StorageCopy->Buffer, Storage->Buffer, Storage->Size);
2384 //
2385 // Copy NameValue list of storage node
2386 //
2387 InitializeListHead (&StorageCopy->NameValueListHead);
2388
2389 NameValueLink = GetFirstNode (&Storage->NameValueListHead);
2390
2391 while (!IsNull (&Storage->NameValueListHead, NameValueLink)) {
2392
2393 NameValueNode = NAME_VALUE_NODE_FROM_LINK (NameValueLink);
2394 CopyNameValueNode = NULL;
2395 CopyNameValueNode = calloc (sizeof (NAME_VALUE_NODE), sizeof (CHAR8));
2396 if (CopyNameValueNode == NULL) {
2397 free (StorageCopy->Name);
2398 free (StorageCopy->Buffer);
2399 free (StorageCopy);
2400 printf ("Memory allocation failed.\n");
2401 return EFI_ABORTED;
2402 }
2403 memcpy (CopyNameValueNode, NameValueNode, sizeof (NAME_VALUE_NODE));
2404
2405 CopyNameValueNode->Name = NULL;
2406 CopyNameValueNode->Value = NULL;
2407 CopyNameValueNode->EditValue = NULL;
2408
2409 CopyNameValueNode->Name = calloc (FceStrLen (NameValueNode->Name) + 1, sizeof (CHAR16));
2410 CopyNameValueNode->Value = calloc (FceStrLen (NameValueNode->Value) + 1, sizeof (CHAR16));
2411 CopyNameValueNode->EditValue = calloc (FceStrLen (NameValueNode->EditValue) + 1, sizeof (CHAR16));
2412 if ((CopyNameValueNode->Name == NULL)
2413 || (CopyNameValueNode->Value == NULL)
2414 || (CopyNameValueNode->EditValue == NULL)
2415 ) {
2416 free (StorageCopy->Name);
2417 free (StorageCopy->Buffer);
2418 free (StorageCopy);
2419 if (CopyNameValueNode->Name != NULL) {
2420 free (CopyNameValueNode->Name );
2421 }
2422 if (CopyNameValueNode->Value != NULL) {
2423 free (CopyNameValueNode->Value);
2424 }
2425 if (CopyNameValueNode->EditValue != NULL) {
2426 free (CopyNameValueNode->EditValue);
2427 }
2428 free (CopyNameValueNode);
2429 printf ("Memory allocation failed.\n");
2430 return EFI_ABORTED;
2431 }
2432 StrCpy (CopyNameValueNode->Name, NameValueNode->Name);
2433 StrCpy (CopyNameValueNode->Value, NameValueNode->Value);
2434 StrCpy (CopyNameValueNode->EditValue, NameValueNode->EditValue);
2435 //
2436 // Insert it to StorageCopy->NameValueListHead
2437 //
2438 InsertTailList(&StorageCopy->NameValueListHead,&CopyNameValueNode->Link);
2439 NameValueLink = GetNextNode (&Storage->NameValueListHead, NameValueLink);
2440 }
2441
2442 //
2443 // Insert it to StorageListHead1
2444 //
2445 InsertTailList(StorageListHead1,&StorageCopy->Link);
2446 }
2447 StorageLink = GetNextNode (StorageListHead2, StorageLink);
2448 }
2449 return EFI_SUCCESS;
2450 }
2451
2452 /**
2453 Check whether the current defaultId and platfrom is equal to the first one of one
2454 group of defaultId and platformId which have the same variable data.
2455
2456 @param DefaultId The default Id
2457 @param PlatformId The platform Id
2458
2459 @retval TRUE If not equal to the first defaultId and platformId, return TRUE
2460 @return EFI_ABORTED Others
2461 **/
2462 BOOLEAN
2463 NoTheKeyIdOfGroup (
2464 IN UINT16 DefaultId,
2465 IN UINT64 PlatformId
2466 )
2467 {
2468 UINT32 Index;
2469
2470 for (Index = 0; Index < mMultiPlatformParam.KeyIdNum; Index++) {
2471 if (
2472 (DefaultId == mMultiPlatformParam.KeyDefaultId[Index])
2473 && (PlatformId == mMultiPlatformParam.KeyPlatformId[Index])
2474 ) {
2475 return FALSE;
2476 }
2477 }
2478 return TRUE;
2479 }
2480
2481 /**
2482 Evaluate the value in all formset according to the defaultId and platformId.
2483
2484 If not the multi-platform mode, the defaultId is 0. In this case, the
2485 platform Id will be the default value of that question.
2486
2487 @param UpdateMode It will be TRUE in update Mode
2488
2489 @retval EFI_SUCCESS It was complete successfully
2490 @return EFI_ABORTED An error occurred
2491 **/
2492 EFI_STATUS
2493 EvaluateTheValueInFormset (
2494 IN BOOLEAN UpdateMode
2495 )
2496 {
2497 EFI_STATUS Status;
2498 UINT16 DefaultId;
2499 UINT64 PlatformId;
2500 UINT16 CurDefaultId;
2501 UINT64 CurPlatformId;
2502 UINT16 DefaultIndex;
2503 UINT16 PlatformIndex;
2504 UINT32 Index;
2505 UQI_PARAM_LIST *CurUqiList;
2506
2507 Status = EFI_SUCCESS;
2508
2509 if (mMultiPlatformParam.MultiPlatformOrNot) {
2510 ScanUqiFullList (mUqiList);
2511
2512 //
2513 // Multi-platform mode support
2514 //
2515 for (DefaultIndex = 0; DefaultIndex < mMultiPlatformParam.DefaultIdNum; DefaultIndex++) {
2516 for (PlatformIndex = 0; PlatformIndex < mMultiPlatformParam.PlatformIdNum; PlatformIndex++) {
2517 DefaultId = mMultiPlatformParam.DefaultId[DefaultIndex];
2518 PlatformId = mMultiPlatformParam.PlatformId[PlatformIndex];
2519 //
2520 //Only parse one time, if a group of defaultId and platformId which have the same variable
2521 // Take the first one as a key Id of a group
2522 //
2523 if (UpdateMode && NoTheKeyIdOfGroup (DefaultId, PlatformId)) {
2524 continue;
2525 }
2526 //
2527 // Initialize the Storage of mVarListEntry
2528 //
2529 ClearStorageEntryList (&mVarListEntry, DefaultId, PlatformId);
2530
2531 Status = ExtractDefault (
2532 NULL,
2533 NULL,
2534 DefaultId,
2535 PlatformId,
2536 SystemLevel
2537 );
2538 if (EFI_ERROR (Status)) {
2539 return EFI_ABORTED;
2540 }
2541 //
2542 // Clear the platformId as 0 after calculation.
2543 //
2544 Status = AssignThePlatformId (0);
2545 if (EFI_ERROR (Status)) {
2546 printf ("Failed to clear the platformid.\n");
2547 return Status;
2548 }
2549 //
2550 // Update the value from script file
2551 //
2552 if (UpdateMode) {
2553 SetUqiParametersMultiMode (mUqiList,DefaultId, PlatformId);
2554 }
2555 //
2556 // If not existed the same variables in mAllVarListEntry, insert the new ones.
2557 // Or else, only add the defaultId and platformId to the former one.
2558 //
2559 if (ComparePartSameVariableList (&mAllVarListEntry, &mVarListEntry, &CurDefaultId, &CurPlatformId)) {
2560 AppendIdToVariables (&mAllVarListEntry, CurDefaultId, CurPlatformId, DefaultId, PlatformId);
2561 } else {
2562 //
2563 // Copy Stroage from mVarListEntry to mAllVarListEntry and assign the defaultId and platformId as well
2564 //
2565 Status = BuildVariableList (&mAllVarListEntry, &mVarListEntry, DefaultId, PlatformId, TRUE, UPDATE);
2566 if (EFI_ERROR (Status)) {
2567 return EFI_ABORTED;
2568 }
2569 //
2570 // In update mode, add the other defaultId and platform of a group to the variale list
2571 //
2572 if (UpdateMode) {
2573 CurUqiList = mUqiList;
2574
2575 while (CurUqiList != NULL) {
2576 if ((DefaultId == CurUqiList->Header.DefaultId[0])
2577 && (PlatformId == CurUqiList->Header.PlatformId[0])
2578 ) {
2579 break;
2580 }
2581 CurUqiList = CurUqiList->Next;
2582 }
2583
2584 if (CurUqiList == NULL) {
2585 return EFI_ABORTED;
2586 }
2587
2588 for (Index = 1; Index < CurUqiList->Header.IdNum; Index++) {
2589 CurDefaultId = CurUqiList->Header.DefaultId[Index];
2590 CurPlatformId = CurUqiList->Header.PlatformId[Index];
2591 AppendIdToVariables (&mAllVarListEntry, DefaultId, PlatformId, CurDefaultId, CurPlatformId);
2592 }
2593 }
2594 }
2595 }
2596 }
2597 } else {
2598 //
2599 // General mode
2600 //
2601 Status = ExtractDefault (
2602 NULL,
2603 NULL,
2604 0,
2605 0,
2606 SystemLevel
2607 );
2608 if (EFI_ERROR (Status)) {
2609 return EFI_ABORTED;
2610 }
2611 //
2612 // If existed the variable in NvStorage, copy them to mVarListEntry.
2613 // Synchronize the default value from the EFI variable zone to variable list
2614 //
2615 Status = EfiVarAndListExchange (TRUE, &mVarListEntry);
2616 if (Status == EFI_INVALID_PARAMETER) {
2617 Status = EFI_ABORTED;
2618 return Status;
2619 }
2620 //
2621 // Update the value from script file
2622 //
2623 if (UpdateMode) {
2624 Status = SetUqiParameters (mUqiList,0, 0);
2625 if (EFI_ERROR (Status)) {
2626 return EFI_ABORTED;
2627 }
2628 }
2629 //
2630 // Copy Stroage from mVarListEntry to mAllVarListEntry
2631 //
2632 Status = BuildVariableList (&mAllVarListEntry, &mVarListEntry, 0, 0, TRUE, UPDATE);
2633 if (EFI_ERROR (Status)) {
2634 return EFI_ABORTED;
2635 }
2636 }
2637 return EFI_SUCCESS;
2638 }
2639
2640 /**
2641 Check and compare the value between the script file and variable from BFV.
2642
2643 It's used in the update operation of multi-plaform mode.
2644
2645 @retval EFI_SUCCESS It was complete successfully
2646 @return EFI_ABORTED An error occurred
2647 **/
2648 static
2649 EFI_STATUS
2650 CheckValueUpdateList (
2651 VOID
2652 )
2653 {
2654 UINT16 DefaultId;
2655 UINT64 PlatformId;
2656 UINT16 DefaultIndex;
2657 UINT16 PlatformIndex;
2658 EFI_STATUS Status;
2659 FORMSET_STORAGE *Storage;
2660 LIST_ENTRY *StorageLink;
2661 UINT16 PreDefaultId;
2662 UINT64 PrePlatformId;
2663
2664 Storage = NULL;
2665 PreDefaultId = 0xFFFF;
2666 PrePlatformId = 0xFFFFFFFFFFFFFFFF;
2667
2668 ScanUqiFullList (mUqiList);
2669 if (gEfiFdInfo.ExistNvStoreDatabase) {
2670 StorageLink = GetFirstNode (&mBfvVarListEntry);
2671 while (!IsNull (&mBfvVarListEntry, StorageLink)) {
2672 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
2673 if (PreDefaultId == Storage->DefaultId[0] && PrePlatformId == Storage->PlatformId[0]) {
2674 StorageLink = GetNextNode (&mBfvVarListEntry, StorageLink);
2675 continue;
2676 } else {
2677 PreDefaultId = Storage->DefaultId[0];
2678 PrePlatformId = Storage->PlatformId[0];
2679 }
2680 DefaultId = PreDefaultId;
2681 PlatformId = PrePlatformId;
2682 //
2683 //Only parse one time, if a group of defaultId and platformId which have the same variable
2684 // Take the first one as a key Id of a group
2685 //
2686 if (NoTheKeyIdOfGroup (DefaultId, PlatformId)) {
2687 continue;
2688 }
2689 //
2690 // Copy Stroage from mBfvVarListEntry to mVarListEntry. The mVarListEntry was attached to
2691 // the FormSet->StorageListHead.
2692 //
2693 DestroyAllStorage (&mVarListEntry);
2694 Status = BuildVariableList (&mVarListEntry, &mBfvVarListEntry, DefaultId, PlatformId, FALSE, UPDATE);
2695 if (EFI_ERROR (Status)) {
2696 return EFI_ABORTED;
2697 }
2698 SetUqiParametersMultiMode (mUqiList,DefaultId, PlatformId);
2699 //
2700 // Copy Stroage from mVarListEntry to mAllVarListEntry and assign the defaultId and platformId as well
2701 //
2702 Status = BuildVariableList (&mAllVarListEntry, &mVarListEntry, DefaultId, PlatformId, TRUE, UPDATE);
2703 if (EFI_ERROR (Status)) {
2704 return EFI_ABORTED;
2705 }
2706 StorageLink = GetNextNode (&mBfvVarListEntry, StorageLink);
2707 }
2708 } else {
2709 for (DefaultIndex = 0; DefaultIndex < mMultiPlatformParam.DefaultIdNum; DefaultIndex++) {
2710 for (PlatformIndex = 0; PlatformIndex < mMultiPlatformParam.PlatformIdNum; PlatformIndex++) {
2711 DefaultId = mMultiPlatformParam.DefaultId[DefaultIndex];
2712 PlatformId = mMultiPlatformParam.PlatformId[PlatformIndex];
2713 //
2714 //Only parse one time, if a group of defaultId and platformId which have the same variable
2715 // Take the first one as a key Id of a group
2716 //
2717 if (NoTheKeyIdOfGroup (DefaultId, PlatformId)) {
2718 continue;
2719 }
2720 //
2721 // Copy Stroage from mBfvVarListEntry to mVarListEntry. The mVarListEntry was attached to
2722 // the FormSet->StorageListHead.
2723 //
2724 DestroyAllStorage (&mVarListEntry);
2725 Status = BuildVariableList (&mVarListEntry, &mBfvVarListEntry, DefaultId, PlatformId, FALSE, UPDATE);
2726 if (EFI_ERROR (Status)) {
2727 return EFI_ABORTED;
2728 }
2729 SetUqiParametersMultiMode (mUqiList,DefaultId, PlatformId);
2730 //
2731 // Copy Stroage from mVarListEntry to mAllVarListEntry and assign the defaultId and platformId as well
2732 //
2733 Status = BuildVariableList (&mAllVarListEntry, &mVarListEntry, DefaultId, PlatformId, TRUE, UPDATE);
2734 if (EFI_ERROR (Status)) {
2735 return EFI_ABORTED;
2736 }
2737 }
2738 }
2739 }
2740 return EFI_SUCCESS;
2741 }
2742 /**
2743 Read defaultId and platformId from the whole FD, and store these two values to mMultiPlatformParam.
2744
2745 If not multi-platform mode, only return EFI_ABORTED.
2746
2747 @param Fv the Pointer to the FFS
2748 @param Length the length of FFS
2749
2750 @retval EFI_SUCCESS It was complete successfully
2751 @return EFI_ABORTED An error occurred
2752 **/
2753 static
2754 EFI_STATUS
2755 ReadAllIfrToFromset (
2756 IN VOID *Fv,
2757 IN UINTN Length
2758 )
2759 {
2760 UINT8 NumberofMachingVfrBin;
2761 UINTN *VfrBinBaseAddress;
2762 UINTN *UniBinBaseAddress;
2763 EFI_STATUS Status;
2764 UINT8 Index;
2765 EFI_SECTION_STRUCT *EfiBufferHeader;
2766 VOID *EfiAddr;
2767
2768 NumberofMachingVfrBin = 0;
2769 VfrBinBaseAddress = NULL;
2770 UniBinBaseAddress = NULL;
2771 Status = EFI_SUCCESS;
2772 EfiBufferHeader = NULL;
2773 EfiAddr = NULL;
2774
2775 //
2776 // Locate the efi base address
2777 //
2778 EfiBufferHeader = malloc (sizeof (EFI_SECTION_STRUCT));
2779 if (EfiBufferHeader == NULL) {
2780 return EFI_ABORTED;
2781 }
2782 memset (
2783 EfiBufferHeader,
2784 0,
2785 sizeof (EFI_SECTION_STRUCT)
2786 );
2787
2788 Status = ParseSection (
2789 TRUE,
2790 (UINT8 *)Fv,
2791 Length,
2792 &EfiBufferHeader
2793 );
2794 if (Status != EFI_SUCCESS) {
2795 Status = EFI_ABORTED;
2796 goto Done;
2797 }
2798
2799 EfiAddr = (VOID *)EfiBufferHeader->BufferBase;
2800 //
2801 //Search the Offset at the end of FFS, whatever it is compressed or not
2802 //
2803 Status = SearchVfrBinInFFS (Fv, EfiAddr, Length, &VfrBinBaseAddress, &NumberofMachingVfrBin);
2804 if (Status != EFI_SUCCESS) {
2805 Status = EFI_ABORTED;
2806 goto Done;
2807 }
2808 Status = SearchUniBinInFFS (
2809 Fv,
2810 EfiAddr,
2811 Length,
2812 &UniBinBaseAddress
2813 );
2814 if (Status != EFI_SUCCESS) {
2815 Status = EFI_ABORTED;
2816 goto Done;
2817 }
2818 //
2819 // Read all Ifr information into Formset and Form structure
2820 //
2821 for (Index = 0; Index < NumberofMachingVfrBin; Index++) {
2822 if ((EfiBufferHeader->BufferBase + EfiBufferHeader->Length) < *(VfrBinBaseAddress + Index)
2823 || (EfiBufferHeader->BufferBase + EfiBufferHeader->Length) < *UniBinBaseAddress
2824 ) {
2825 printf ("Failed to locate Ifr data from efi by the offset.\n");
2826 Status = EFI_ABORTED;
2827 goto Done;
2828 }
2829 Status = ParseFormSetInVfrBin (
2830 (UINTN **)VfrBinBaseAddress,
2831 (UINTN *)*UniBinBaseAddress,
2832 Index
2833 );
2834 if (EFI_ERROR (Status)) {
2835 Status = EFI_ABORTED;
2836 goto Done;
2837 }
2838 }
2839
2840 Done:
2841 //
2842 // Free the memory which stores the offset
2843 //
2844 if (VfrBinBaseAddress != NULL) {
2845 free (VfrBinBaseAddress);
2846 }
2847 if (UniBinBaseAddress != NULL) {
2848 free (UniBinBaseAddress);
2849 }
2850 //
2851 // Free the memory for uncompressed space in section
2852 //
2853 for (Index = 0; Index < EfiBufferHeader->UnCompressIndex; Index++) {
2854 if ((VOID *)EfiBufferHeader->UncompressedBuffer[Index] != NULL) {
2855 free ((VOID *)EfiBufferHeader->UncompressedBuffer[Index]);
2856 }
2857 }
2858 return Status;
2859 }
2860
2861 /**
2862 Get next questions of four kinds in FormSet list.
2863
2864 If not one kinds of ONE_OF CHECK_BOX ORDER_LIST and NUMERIC, continue to parse next question.
2865 If parse to the end of questions, return NULL.
2866
2867 @param FormSetEntryListHead the pointer to the LIST_ENTRY
2868 @param OrderOfQuestion the order of question
2869
2870 @retval If succeed, return the pointer to the question
2871 @return NULL
2872 **/
2873 FORM_BROWSER_STATEMENT *
2874 GetNextQuestion (
2875 IN LIST_ENTRY *FormSetEntryListHead,
2876 IN OUT UINT32 *OrderOfQuestion
2877 )
2878 {
2879 FORM_BROWSER_FORMSET *FormSet;
2880 LIST_ENTRY *FormSetLink;
2881 FORM_BROWSER_FORM *Form;
2882 LIST_ENTRY *FormLink;
2883 FORM_BROWSER_STATEMENT *Question;
2884 LIST_ENTRY *QuestionLink;
2885 UINT32 Index;
2886
2887 FormSet = NULL;
2888 FormSetLink = NULL;
2889 Form = NULL;
2890 FormLink = NULL;
2891 Question = NULL;
2892 QuestionLink = NULL;
2893 Index = 0;
2894
2895 FormSetLink = GetFirstNode (FormSetEntryListHead);
2896 while (!IsNull (FormSetEntryListHead, FormSetLink)) {
2897 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
2898 //
2899 // Parse all forms in formset
2900 //
2901 FormLink = GetFirstNode (&FormSet->FormListHead);
2902
2903 while (!IsNull (&FormSet->FormListHead, FormLink)) {
2904 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
2905 //
2906 // Parse five kinds of Questions in Form
2907 //
2908 QuestionLink = GetFirstNode (&Form->StatementListHead);
2909
2910 while (!IsNull (&Form->StatementListHead, QuestionLink)) {
2911 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
2912 //
2913 // Parse five kinds of Questions in Form
2914 //
2915 if ((Question->Operand == EFI_IFR_ONE_OF_OP)
2916 || (Question->Operand == EFI_IFR_NUMERIC_OP)
2917 || (Question->Operand == EFI_IFR_CHECKBOX_OP)
2918 || (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
2919 || (Question->Operand == EFI_IFR_STRING_OP)
2920 ) {
2921 if (*OrderOfQuestion == Index++) {
2922 (*OrderOfQuestion)++;
2923 return Question;
2924 }
2925 }
2926 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
2927 }
2928
2929 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
2930 }
2931 FormSetLink = GetNextNode (FormSetEntryListHead, FormSetLink);
2932 }
2933 return NULL;
2934 }
2935
2936 /**
2937 Read defaultId and platformId from the whole FD, and store these two values to mMultiPlatformParam.
2938
2939 If not multi-platform mode, only return EFI_ABORTED.
2940
2941 @param Fv the Pointer to the FFS
2942 @param Length the length of FFS
2943
2944 @retval EFI_SUCCESS It was complete successfully
2945 @return EFI_ABORTED An error occurred
2946 **/
2947 static
2948 EFI_STATUS
2949 ReadDefaultAndPlatformId (
2950 IN LIST_ENTRY *FormSetEntryListHead
2951 )
2952 {
2953 EFI_STATUS Status;
2954 FORM_BROWSER_FORMSET *FormSet;
2955 LIST_ENTRY *FormLink;
2956 FORMSET_DEFAULTSTORE *DefaultStore;
2957 LIST_ENTRY *DefaultStoreLink;
2958 FORM_BROWSER_STATEMENT *CurQuestion;
2959 UINT32 MatchedNum;
2960 UINT32 QuestionOrder;
2961
2962 Status = EFI_SUCCESS;
2963 CurQuestion = NULL;
2964 MatchedNum = 0;
2965 QuestionOrder = 0;
2966 //
2967 //Check whether it is the Multi-Platform solution or not
2968 //
2969 if (!mMultiPlatformParam.MultiPlatformOrNot) {
2970 Status = EFI_SUCCESS;
2971 goto Done;
2972 }
2973 //
2974 // Read defaultId from FormSet List
2975 //
2976 FormLink = GetFirstNode (FormSetEntryListHead);
2977 while (!IsNull (FormSetEntryListHead, FormLink)) {
2978 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormLink);
2979 //
2980 // Parse Default Store in formset
2981 //
2982 DefaultStoreLink = GetFirstNode (&FormSet->DefaultStoreListHead);
2983
2984 while (!IsNull (&FormSet->DefaultStoreListHead, DefaultStoreLink)) {
2985 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (DefaultStoreLink);
2986 StoreAllDefaultId (DefaultStore->DefaultId);
2987 DefaultStoreLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultStoreLink);
2988 }
2989 FormLink = GetNextNode (FormSetEntryListHead, FormLink);
2990 }
2991
2992 //
2993 //Read the platformId from FormSetList
2994 //
2995 while ((CurQuestion = GetNextQuestion (FormSetEntryListHead, &QuestionOrder)) != NULL) {
2996 Status = ReadPlaformId (CurQuestion);
2997 if (!EFI_ERROR (Status)) {
2998 MatchedNum++;
2999 }
3000 }
3001
3002 if (MatchedNum == 0) {
3003 printf ("There are no questions included in the platformid in the FD.");
3004 Status = EFI_ABORTED;
3005 } else if (MatchedNum > 1) {
3006 printf ("There are %d questions included in the platformid in the FD.", MatchedNum);
3007 Status = EFI_ABORTED;
3008 } else {
3009 Status = EFI_SUCCESS;
3010 }
3011
3012 Done:
3013
3014 return Status;
3015 }
3016
3017 /**
3018 Read the first two bytes to check whether it is Ascii or UCS2.
3019
3020 @param ScriptFile Pointer to the script file.
3021
3022 @reture TRUE If ascii, return TRUE
3023 @reture FALSE Others, return FALSE.
3024
3025 **/
3026 FILE_TYPE
3027 IsAsciiOrUcs2 (
3028 IN FILE *ScriptFile
3029 )
3030 {
3031 CHAR16 FirstTwoBytes;
3032
3033 fread(&FirstTwoBytes, 1, 2, ScriptFile);
3034
3035 if (FirstTwoBytes == BigUnicodeFileTag) {
3036 return BIG_UCS2;
3037 } else if (FirstTwoBytes == LittleUnicodeFileTag) {
3038 return LITTLE_UCS2;
3039 } else {
3040 return ASCII;
3041 }
3042 }
3043
3044 /**
3045 Read Unicode characters and transfer it to ASCII.
3046
3047 @param ScriptFile The pointer to the script file.
3048 @param Type The type of BigUCS2 or LittleUCS2
3049
3050 @return The ASCII characters
3051
3052 **/
3053 CHAR8 *
3054 ReadUcs2ToStr (
3055 IN OUT FILE *ScriptFile,
3056 IN FILE_TYPE Type
3057 )
3058 {
3059 CHAR16 TempChar16;
3060 CHAR16 TempChar8;
3061 CHAR8 *StrChar8;
3062 UINTN Index;
3063 BOOLEAN FirstParse;
3064
3065 TempChar16 = L'\0';
3066 TempChar8 = '\0';
3067 StrChar8 = NULL;
3068 Index = 0;
3069 FirstParse = TRUE;
3070
3071 if (ScriptFile == NULL) {
3072 return NULL;
3073 }
3074 StrChar8 = calloc (MAX_STR_LEN_FOR_PICK_UQI, sizeof (CHAR8));
3075 assert (StrChar8);
3076
3077 for (Index = 0; Index < MAX_STR_LEN_FOR_PICK_UQI; Index++) {
3078 //
3079 // The first parse should skip the 0x0020 (BigUCS2) or 0x2000 (LittleUCS2)
3080 //
3081 if (FirstParse) {
3082 do {
3083 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3084 } while ((TempChar16 == 0x0020) || (TempChar16 == 0x2000));
3085 FirstParse = FALSE;
3086 } else {
3087 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3088 }
3089 //
3090 // Read until break the "Space"
3091 //
3092 if ((TempChar16 == 0x0020) || (TempChar16 == 0x2000)) {
3093 break;
3094 }
3095 if (Type == BIG_UCS2) {
3096 TempChar8 = (CHAR8)TempChar16;
3097 } else {
3098 TempChar8 = (CHAR8)(TempChar16 >> 8);
3099 }
3100 memcpy (StrChar8 + Index, &TempChar8, 0x1);
3101 }
3102 if (Index == MAX_STR_LEN_FOR_PICK_UQI) {
3103 free (StrChar8);
3104 return NULL;
3105 }
3106 *(StrChar8 + Index) = '\0';
3107
3108 return StrChar8;
3109 }
3110
3111 /**
3112 Read Unicode characters and transfer it to ASCII.
3113
3114 @param AsciiStr The pointer to the Ascii string. It may inlcudes blank space.
3115 @param IdArray The pointer to the array of Id.
3116
3117 @return The number of default or platform Id
3118
3119 **/
3120 static
3121 UINT16
3122 GetNumFromAsciiString (
3123 IN CHAR8 *AsciiStr,
3124 IN OUT UINT64 *IdArray
3125 )
3126 {
3127 UINT16 Index1;
3128 UINT16 Index2;
3129 UINT16 NumofId;
3130 CHAR8 CharArray[16];
3131 BOOLEAN ExistedValue;
3132
3133 Index1 = 0;
3134 Index2 = 0;
3135 NumofId = 0;
3136 ExistedValue = FALSE;
3137
3138 while (*(AsciiStr + Index1) != '\n') {
3139
3140 Index2 = 0;
3141 ExistedValue = FALSE;
3142 memset (CharArray, 0, 16);
3143 for (; *(AsciiStr + Index1) == ' '; Index1++);
3144 for (; (*(AsciiStr + Index1) != ' ') && (*(AsciiStr + Index1) != '\n'); Index1++) {
3145 assert (Index2 <= 15);
3146 *(CharArray + Index2++) = *(AsciiStr + Index1);
3147 ExistedValue = TRUE;
3148 }
3149 if (ExistedValue && (*(AsciiStr + Index1 - 1) != '\n')) {
3150 sscanf(CharArray, "%lld", (long long *)&IdArray[NumofId++]);
3151 }
3152 }
3153 return NumofId;
3154 }
3155
3156 /**
3157 Parse the script file to build the linked list of question structures.
3158
3159 Pick up the UQI information and save it to the UqiList. The current scripts
3160 could be Ascii or UCS2 (Little or Big Mode).
3161
3162 @param ScriptFile The pointer to the script file.
3163
3164 @return EFI_SUCCESS
3165 @return EFI_INVALID_PARAMETER ScriptFile is NULL
3166
3167 **/
3168 static
3169 EFI_STATUS
3170 PickUpUqiFromScript (
3171 IN FILE *ScriptFile
3172 )
3173 {
3174 CHAR8 TempChar;
3175 BOOLEAN InQuote;
3176 CHAR16 TempChar16;
3177 UINT32 UqiSize;
3178 CHAR16 *UqiBuffer;
3179 CHAR8 Type[32];
3180 UINT16 Index;
3181 UQI_PARAM_LIST *UqiNode;
3182 UINTN MaxContainers;
3183 UINT32 ScriptsLine;
3184 FILE_TYPE AsciiOrUcs2;
3185 CHAR8 *Char8Str;
3186 CHAR8 DefaultIdStr[30];
3187 CHAR8 PlatformIdStr[30];
3188 CHAR8 PlatformUqi[30];
3189 UINT16 Index1;
3190 UINT16 Index2;
3191 UINT16 Index3;
3192 UINT16 Index4;
3193 UINT16 Index5;
3194 BOOLEAN ReadDefaultId;
3195 BOOLEAN ReadPlatformId;
3196 BOOLEAN ReadPlatformIdUqi;
3197 UINT64 DefaultId[MAX_PLATFORM_DEFAULT_ID_NUM];
3198 UINT64 PlatformId[MAX_PLATFORM_DEFAULT_ID_NUM];
3199 UINT16 DefaultIdNum;
3200 UINT16 PlatformIdNum;
3201 UINT8 Array[MAX_PLATFORM_DEFAULT_ID_NUM * MAX_PLATFORM_DEFAULT_ID_NUM];
3202 UINT16 IdStart;
3203 UINT16 IdEnd;
3204
3205 Char8Str = NULL;
3206 ScriptsLine = 0;
3207 AsciiOrUcs2 = ASCII;
3208 Index1 = 0;
3209 Index2 = 0;
3210 Index3 = 0;
3211 Index4 = 0;
3212 Index5 = 0;
3213 ReadDefaultId = FALSE;
3214 ReadPlatformId = FALSE;
3215 ReadPlatformIdUqi = FALSE;
3216 DefaultIdNum = 1;
3217 PlatformIdNum = 1;
3218 InQuote = FALSE;
3219
3220 memset (DefaultId, 0, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
3221 memset (PlatformId, 0, MAX_PLATFORM_DEFAULT_ID_NUM * sizeof (UINT64));
3222 memcpy (DefaultIdStr, "/ FCEKEY DEFAULT_ID:", strlen ("/ FCEKEY DEFAULT_ID:") + 1);
3223 memcpy (PlatformIdStr,"/FCEKEY PLATFORM_ID:", strlen ("/FCEKEY PLATFORM_ID:") + 1);
3224 memcpy (PlatformUqi, "/FCEKEY PLATFORM_UQI:", strlen ("/FCEKEY PLATFORM_UQI:") + 1);
3225
3226 if (ScriptFile == NULL) {
3227 return EFI_INVALID_PARAMETER;
3228 }
3229 //
3230 // Check the file type
3231 //
3232 AsciiOrUcs2 = IsAsciiOrUcs2 (ScriptFile);
3233 if (AsciiOrUcs2 == ASCII) {
3234 fseek (ScriptFile, 0, SEEK_SET);
3235 }
3236
3237 while(!feof(ScriptFile)) {
3238 //
3239 // Reset local data
3240 //
3241 TempChar = '\0';
3242 TempChar16 = L'\0';
3243 UqiSize = 0;
3244 UqiBuffer = NULL;
3245 MaxContainers = 0;
3246 UqiNode = NULL;
3247 memset(Type, 0, 32);
3248 //
3249 // Read first character of the line to find the line type
3250 //
3251 if (AsciiOrUcs2 == ASCII) {
3252 fread(&TempChar, sizeof (CHAR8), 1, ScriptFile);
3253 } else {
3254 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3255 if (AsciiOrUcs2 == BIG_UCS2) {
3256 TempChar = (CHAR8)TempChar16;
3257 } else {
3258 TempChar = (CHAR8)(TempChar16 >> 8);
3259 }
3260 }
3261 //
3262 // Take "\n\r" one line
3263 //
3264 if (TempChar != 0x0d) {
3265 ScriptsLine++;
3266 }
3267 switch (TempChar) {
3268
3269 case 'Q':
3270 //
3271 // Process question line
3272 //
3273 // Read size of UQI string
3274 //
3275 if (AsciiOrUcs2 == ASCII) {
3276 fscanf(ScriptFile, " %x", (INT32 *)&UqiSize);
3277 } else {
3278 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3279 if (Char8Str == NULL) {
3280 return EFI_ABORTED;
3281 }
3282 sscanf(Char8Str, " %x", (INT32 *)&UqiSize);
3283 if (Char8Str != NULL) {
3284 free (Char8Str);
3285 Char8Str = NULL;
3286 }
3287 }
3288 if (UqiSize > MAX_INPUT_ALLOCATE_SIZE) {
3289 return EFI_ABORTED;
3290 }
3291 if (UqiSize == 0) {
3292 do {
3293 if (AsciiOrUcs2 == ASCII) {
3294 fread(&TempChar, sizeof (CHAR8), 1, ScriptFile);
3295 } else {
3296 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3297 if (AsciiOrUcs2 == BIG_UCS2) {
3298 TempChar = (CHAR8)TempChar16;
3299 } else {
3300 TempChar = (CHAR8)(TempChar16 >> 8);
3301 }
3302 }
3303 } while((TempChar != '\n') && !feof(ScriptFile));
3304 break;
3305 }
3306 //
3307 // Malloc buffer for string size + null termination
3308 //
3309 UqiBuffer = (CHAR16 *)calloc(UqiSize + 1, sizeof(CHAR16));
3310
3311 if (UqiBuffer == NULL) {
3312 printf("Error. Unable to allocate 0x%04lx bytes for UQI string -- FAILURE\n", (unsigned long)((UqiSize + 1) * sizeof(CHAR16)));
3313 break;
3314 }
3315 //
3316 // Read UQI string
3317 //
3318 for (Index = 0; Index < UqiSize; Index++) {
3319 if (AsciiOrUcs2 == ASCII) {
3320 fscanf(ScriptFile, " %hx", (short *)&(UqiBuffer[Index]));
3321 } else {
3322 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3323 if (Char8Str == NULL) {
3324 free (UqiBuffer );
3325 return EFI_ABORTED;
3326 }
3327 sscanf(Char8Str, " %hx", (short *)&(UqiBuffer[Index]));
3328 if (Char8Str != NULL) {
3329 free (Char8Str);
3330 Char8Str = NULL;
3331 }
3332 }
3333 }
3334 //
3335 // Set null termination
3336 //
3337 UqiBuffer[Index] = 0;
3338 //
3339 // Read question type
3340 //
3341 if (AsciiOrUcs2 == ASCII) {
3342 fscanf(ScriptFile, "%31s", Type);
3343 } else {
3344 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3345 if (Char8Str == NULL) {
3346 free (UqiBuffer);
3347 return EFI_ABORTED;
3348 }
3349 sscanf(Char8Str, " %31s", Type);
3350 if (Char8Str != NULL) {
3351 free (Char8Str);
3352 Char8Str = NULL;
3353 }
3354 }
3355 if (stricmp(Type, "ONE_OF") == 0) {
3356 UqiNode = CreateInsertUqiNode ();
3357 if (UqiNode == NULL) {
3358 free (UqiBuffer);
3359 return EFI_ABORTED;
3360 }
3361 UqiNode->Header.Type = ONE_OF;
3362 UqiNode->Header.HexNum = UqiSize;
3363 UqiNode->Header.Data = UqiBuffer;
3364 UqiNode->Header.Value = (UINT8 *)calloc(1, sizeof(UINT64));
3365 UqiNode->Header.DiffValue = (UINT8 *)calloc(1, sizeof(UINT64));
3366 UqiNode->Header.IdNum = PlatformIdNum;
3367 UqiNode->Header.DefaultId = (UINT16 *)calloc (PlatformIdNum, sizeof (UINT16));
3368 if (UqiNode->Header.DefaultId == NULL) {
3369 printf("Fail to allocate memory");
3370 return EFI_OUT_OF_RESOURCES;
3371 }
3372 UqiNode->Header.PlatformId = (UINT64 *)calloc (PlatformIdNum, sizeof (UINT64));
3373 if (UqiNode->Header.PlatformId == NULL) {
3374 printf("Fail to allocate memory");
3375 return EFI_OUT_OF_RESOURCES;
3376 }
3377 for (Index5 = 0; Index5 < PlatformIdNum; Index5++) {
3378 UqiNode->Header.DefaultId[Index5] = (UINT16)DefaultId[Index5];
3379 }
3380 memcpy (UqiNode->Header.PlatformId, PlatformId, PlatformIdNum * sizeof (UINT64));
3381
3382 if (AsciiOrUcs2 == ASCII) {
3383 fscanf(ScriptFile, " %llx", (long long *)UqiNode->Header.Value);
3384 } else {
3385 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3386 if (Char8Str == NULL) {
3387 return EFI_ABORTED;
3388 }
3389 sscanf(Char8Str, " %llx", (long long *)UqiNode->Header.Value);
3390 if (Char8Str != NULL) {
3391 free (Char8Str);
3392 Char8Str = NULL;
3393 }
3394 }
3395
3396 } else if (stricmp(Type, "CHECKBOX") == 0) {
3397 UqiNode = CreateInsertUqiNode ();
3398 if (UqiNode == NULL) {
3399 free (UqiBuffer);
3400 return EFI_ABORTED;
3401 }
3402 UqiNode->Header.Type = CHECKBOX;
3403 UqiNode->Header.HexNum = UqiSize;
3404 UqiNode->Header.Data = UqiBuffer;
3405 UqiNode->Header.Value = (UINT8 *)calloc(1, sizeof(UINT64));
3406 UqiNode->Header.DiffValue = (UINT8 *)calloc(1, sizeof(UINT64));
3407 UqiNode->Header.IdNum = PlatformIdNum;
3408 UqiNode->Header.DefaultId = (UINT16 *)calloc (PlatformIdNum, sizeof (UINT16));
3409 if (UqiNode->Header.DefaultId == NULL) {
3410 printf ("Fali to allocate memory!\n");
3411 return EFI_OUT_OF_RESOURCES;
3412 }
3413 UqiNode->Header.PlatformId = (UINT64 *)calloc (PlatformIdNum, sizeof (UINT64));
3414 if (UqiNode->Header.PlatformId == NULL) {
3415 printf ("Fali to allocate memory!\n");
3416 return EFI_OUT_OF_RESOURCES;
3417 }
3418 for (Index5 = 0; Index5 < PlatformIdNum; Index5++) {
3419 UqiNode->Header.DefaultId[Index5] = (UINT16)DefaultId[Index5];
3420 }
3421 memcpy (UqiNode->Header.PlatformId, PlatformId, PlatformIdNum * sizeof (UINT64));
3422
3423 if (AsciiOrUcs2 == ASCII) {
3424 fscanf(ScriptFile, " %llx", (long long *)UqiNode->Header.Value);
3425 } else {
3426 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3427 if (Char8Str == NULL) {
3428 return EFI_ABORTED;
3429 }
3430 sscanf(Char8Str, " %llx", (long long *)UqiNode->Header.Value);
3431 if (Char8Str != NULL) {
3432 free (Char8Str);
3433 Char8Str = NULL;
3434 }
3435 }
3436
3437 } else if (stricmp(Type, "STRING") == 0) {
3438 UqiNode = CreateInsertUqiNode ();
3439 if (UqiNode == NULL) {
3440 free (UqiBuffer);
3441 return EFI_ABORTED;
3442 }
3443
3444 UqiNode->Header.Type = STRING;
3445 UqiNode->Header.HexNum = UqiSize;
3446 UqiNode->Header.Data = UqiBuffer;
3447 UqiNode->Header.Value = (UINT8 *)calloc(MAX_INPUT_ALLOCATE_SIZE, sizeof(CHAR16));
3448 UqiNode->Header.DiffValue = (UINT8 *)calloc(MAX_INPUT_ALLOCATE_SIZE, sizeof(CHAR16));
3449 if (UqiNode->Header.Value == NULL) {
3450 printf ("Fali to allocate memory!\n");
3451 return EFI_OUT_OF_RESOURCES;
3452 }
3453 if (UqiNode->Header.DiffValue == NULL) {
3454 printf ("Fali to allocate memory!\n");
3455 return EFI_OUT_OF_RESOURCES;
3456 }
3457 UqiNode->Header.IdNum = PlatformIdNum;
3458 UqiNode->Header.DefaultId = (UINT16 *)calloc (PlatformIdNum, sizeof (UINT16));
3459 if (UqiNode->Header.DefaultId == NULL) {
3460 printf ("Fali to allocate memory!\n");
3461 return EFI_OUT_OF_RESOURCES;
3462 }
3463 UqiNode->Header.PlatformId = (UINT64 *)calloc (PlatformIdNum, sizeof (UINT64));
3464 if (UqiNode->Header.PlatformId == NULL) {
3465 printf ("Fali to allocate memory!\n");
3466 return EFI_OUT_OF_RESOURCES;
3467 }
3468 for (Index5 = 0; Index5 < PlatformIdNum; Index5++) {
3469 UqiNode->Header.DefaultId[Index5] = (UINT16)DefaultId[Index5];
3470 }
3471 memcpy (UqiNode->Header.PlatformId, PlatformId, PlatformIdNum * sizeof (UINT64));
3472 InQuote = FALSE;
3473 IdStart = 0;
3474 IdEnd = 0;
3475 for (Index = 0; Index < MAX_INPUT_ALLOCATE_SIZE; Index ++) {
3476 if (AsciiOrUcs2 == ASCII) {
3477 fread(&TempChar, sizeof (CHAR8), 1, ScriptFile);
3478 } else {
3479 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3480 if (AsciiOrUcs2 == BIG_UCS2) {
3481 TempChar = (CHAR8)TempChar16;
3482 } else {
3483 TempChar = (CHAR8)(TempChar16 >> 8);
3484 }
3485 }
3486 if (TempChar == '\"') {
3487 if (InQuote == TRUE) {
3488 InQuote = FALSE;
3489 IdEnd = Index;
3490 } else {
3491 InQuote = TRUE;
3492 IdStart = Index;
3493 }
3494 }
3495 if (Index > IdStart) {
3496 if (InQuote == FALSE) {
3497 break;
3498 }
3499 *(UqiNode->Header.Value + Index - IdStart -1) = TempChar;
3500 Index ++;
3501 }
3502
3503 }
3504 if (IdEnd < IdStart) {
3505 printf("The STRING is not end with \" character!\n");
3506 return EFI_ABORTED;
3507 }
3508 if (IdStart == 0) {
3509 printf("The STRING is not start with \" character!\n");
3510 return EFI_ABORTED;
3511 }
3512
3513 } else if (stricmp(Type, "NUMERIC") == 0) {
3514 UqiNode = CreateInsertUqiNode ();
3515 if (UqiNode == NULL) {
3516 free (UqiBuffer);
3517 return EFI_ABORTED;
3518 }
3519 UqiNode->Header.Type = NUMERIC;
3520 UqiNode->Header.HexNum = UqiSize;
3521 UqiNode->Header.Data = UqiBuffer;
3522 UqiNode->Header.Value = (UINT8 *)calloc(1, sizeof(UINT64));
3523 UqiNode->Header.DiffValue = (UINT8 *)calloc(1, sizeof(UINT64));
3524 UqiNode->Header.IdNum = PlatformIdNum;
3525 UqiNode->Header.DefaultId = (UINT16 *)calloc (PlatformIdNum, sizeof (UINT16));
3526 if (UqiNode->Header.DefaultId == NULL) {
3527 printf ("Fali to allocate memory!\n");
3528 return EFI_OUT_OF_RESOURCES;
3529 }
3530 UqiNode->Header.PlatformId = (UINT64 *)calloc (PlatformIdNum, sizeof (UINT64));
3531 if (UqiNode->Header.PlatformId == NULL) {
3532 printf ("Fali to allocate memory!\n");
3533 return EFI_OUT_OF_RESOURCES;
3534 }
3535 for (Index5 = 0; Index5 < PlatformIdNum; Index5++) {
3536 UqiNode->Header.DefaultId[Index5] = (UINT16)DefaultId[Index5];
3537 }
3538 memcpy (UqiNode->Header.PlatformId, PlatformId, PlatformIdNum * sizeof (UINT64));
3539
3540 if (AsciiOrUcs2 == ASCII) {
3541 fscanf(ScriptFile, " %llx", (long long *)UqiNode->Header.Value);
3542 } else {
3543 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3544 if (Char8Str == NULL) {
3545 return EFI_ABORTED;
3546 }
3547 sscanf(Char8Str, " %llx", (long long *)UqiNode->Header.Value);
3548 if (Char8Str != NULL) {
3549 free (Char8Str);
3550 Char8Str = NULL;
3551 }
3552 }
3553
3554 } else if (stricmp(Type, "ORDERED_LIST") == 0) {
3555 UqiNode = CreateInsertUqiNode ();
3556 if (UqiNode == NULL) {
3557 free (UqiBuffer);
3558 return EFI_ABORTED;
3559 }
3560 UqiNode->Header.Type = ORDERED_LIST;
3561 UqiNode->Header.HexNum = UqiSize;
3562 UqiNode->Header.Data = UqiBuffer;
3563 UqiNode->Header.IdNum = PlatformIdNum;
3564 UqiNode->Header.DefaultId = (UINT16 *)calloc (PlatformIdNum, sizeof (UINT16));
3565 if (UqiNode->Header.DefaultId == NULL) {
3566 printf ("Fali to allocate memory!\n");
3567 return EFI_OUT_OF_RESOURCES;
3568 }
3569 UqiNode->Header.PlatformId = (UINT64 *)calloc (PlatformIdNum, sizeof (UINT64));
3570 if (UqiNode->Header.PlatformId == NULL) {
3571 printf ("Fali to allocate memory!\n");
3572 return EFI_OUT_OF_RESOURCES;
3573 }
3574 for (Index5 = 0; Index5 < PlatformIdNum; Index5++) {
3575 UqiNode->Header.DefaultId[Index5] = (UINT16)DefaultId[Index5];
3576 }
3577 memcpy (UqiNode->Header.PlatformId, PlatformId, PlatformIdNum * sizeof (UINT64));
3578
3579 if (AsciiOrUcs2 == ASCII) {
3580 fscanf(ScriptFile, " %x", (INT32 *)&MaxContainers);
3581 } else {
3582 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3583 if (Char8Str == NULL) {
3584 return EFI_ABORTED;
3585 }
3586 sscanf(Char8Str, " %x", (INT32 *)&MaxContainers);
3587 if (Char8Str != NULL) {
3588 free (Char8Str);
3589 Char8Str = NULL;
3590 }
3591 }
3592 if (MaxContainers > MAX_INPUT_ALLOCATE_SIZE) {
3593 return EFI_ABORTED;
3594 }
3595 UqiNode->Header.Value = (UINT8 *)calloc(MaxContainers + 1, sizeof(UINT64));
3596 if (UqiNode->Header.Value == NULL) {
3597 printf ("Fali to allocate memory!\n");
3598 return EFI_OUT_OF_RESOURCES;
3599 }
3600 UqiNode->Header.DiffValue = (UINT8 *)calloc(MaxContainers + 1, sizeof(UINT64));
3601 if (UqiNode->Header.DiffValue == NULL) {
3602 printf ("Fali to allocate memory!\n");
3603 return EFI_OUT_OF_RESOURCES;
3604 }
3605 *UqiNode->Header.Value = (UINT8) MaxContainers;
3606 *UqiNode->Header.DiffValue = (UINT8) MaxContainers;
3607
3608 for (Index = 1; Index <= MaxContainers; Index++) {
3609 if (*(UqiNode->Header.Value + Index) == '/') {
3610 printf ("Error. Failed to parse the value of ORDERED_LIST.\n");
3611 return EFI_INVALID_PARAMETER;
3612 }
3613 if (AsciiOrUcs2 == ASCII) {
3614 fscanf(ScriptFile, " %llx", ((long long *)UqiNode->Header.Value + Index));
3615 } else {
3616 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3617 if (Char8Str == NULL) {
3618 return EFI_ABORTED;
3619 }
3620 sscanf(Char8Str, " %llx", ((long long *)UqiNode->Header.Value + Index));
3621 if (Char8Str != NULL) {
3622 free (Char8Str);
3623 Char8Str = NULL;
3624 }
3625 }
3626 }
3627
3628 } else {
3629 //
3630 // Unknown type
3631 //
3632 // Free UQI buffer before skipping to next line
3633 //
3634 free(UqiBuffer);
3635 UqiBuffer = NULL;
3636 printf ("Error. Invalid parameters exist in scripts line %d", ScriptsLine);
3637 return EFI_ABORTED;
3638 }
3639 UqiNode->Header.ScriptsLine = ScriptsLine;
3640 //
3641 // Skip to next line
3642 //
3643 do {
3644 if (AsciiOrUcs2 == ASCII) {
3645 fread(&TempChar, sizeof (CHAR8), 1, ScriptFile);
3646 } else {
3647 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3648 if (AsciiOrUcs2 == BIG_UCS2) {
3649 TempChar = (CHAR8)TempChar16;
3650 } else {
3651 TempChar = (CHAR8)(TempChar16 >> 8);
3652 }
3653 }
3654 } while((TempChar != '\n') && !feof(ScriptFile));
3655 break;
3656
3657 case '\n':
3658 case '\r':
3659 //
3660 // Newline, skip to next character
3661 //
3662 break;
3663
3664 case '/':
3665 //
3666 // Get the value of PlatformId and DefaultId from comments
3667 //
3668 do {
3669 if (AsciiOrUcs2 == ASCII) {
3670 fread(&TempChar, sizeof (CHAR8), 1, ScriptFile);
3671 } else {
3672 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3673 if (AsciiOrUcs2 == BIG_UCS2) {
3674 TempChar = (CHAR8)TempChar16;
3675 } else {
3676 TempChar = (CHAR8)(TempChar16 >> 8);
3677 }
3678 }
3679 //
3680 //"/ DefaultId :"
3681 //
3682 if (!ReadDefaultId) {
3683 if (TempChar == DefaultIdStr[Index1]) {
3684 Index1++;
3685 } else {
3686 Index1 = 0;
3687 }
3688 if (Index1 == strlen (DefaultIdStr)) {
3689 Index1 = 0;
3690 Index3 = 0;
3691 memset (Array, 0, MAX_PLATFORM_DEFAULT_ID_NUM * MAX_PLATFORM_DEFAULT_ID_NUM);
3692 ReadDefaultId = TRUE;
3693 mMultiPlatformParam.MultiPlatformOrNot = TRUE;
3694 }
3695 } else if (ReadDefaultId) {
3696 if (TempChar == '\n') {
3697 ReadDefaultId = FALSE;
3698 Array[Index3] = TempChar;
3699 DefaultIdNum = GetNumFromAsciiString ((CHAR8 *)Array, DefaultId);
3700 mMultiPlatformParam.KeyDefaultId[mMultiPlatformParam.KeyIdNum] = (UINT16)DefaultId[0];
3701 } else {
3702 Array[Index3++] = TempChar;
3703 }
3704 }
3705 //
3706 //"/ PlatformId:"
3707 //
3708 if (!ReadPlatformId) {
3709 if (TempChar == PlatformIdStr[Index2]) {
3710 Index2++;
3711 } else {
3712 Index2 = 0;
3713 }
3714 if (Index2 == strlen (PlatformIdStr)) {
3715 Index2 = 0;
3716 Index3 = 0;
3717 memset (Array, 0, MAX_PLATFORM_DEFAULT_ID_NUM * MAX_PLATFORM_DEFAULT_ID_NUM);
3718 ReadPlatformId = TRUE;
3719 }
3720 } else if (ReadPlatformId) {
3721 if (TempChar == '\n') {
3722 ReadPlatformId = FALSE;
3723 Array[Index3] = TempChar;
3724 PlatformIdNum = GetNumFromAsciiString ((CHAR8 *)Array, PlatformId);
3725 //
3726 // Take the first defaultid an platformid as the key of this group
3727 //
3728 mMultiPlatformParam.KeyPlatformId[mMultiPlatformParam.KeyIdNum++] = PlatformId[0];
3729 assert (DefaultIdNum == PlatformIdNum);
3730 } else {
3731 Array[Index3++] = TempChar;
3732 }
3733 }
3734 //
3735 //"/ PlatformIdUqi:"
3736 //
3737 if (!ReadPlatformIdUqi) {
3738 if (TempChar == PlatformUqi[Index4]) {
3739 Index4++;
3740 } else {
3741 Index4 = 0;
3742 }
3743 if (Index4 == strlen (PlatformUqi)) {
3744 Index4 = 0;
3745 Index3 = 0;
3746 memset (Array, 0, MAX_PLATFORM_DEFAULT_ID_NUM * MAX_PLATFORM_DEFAULT_ID_NUM);
3747 ReadPlatformIdUqi = TRUE;
3748 }
3749 } else if (ReadPlatformIdUqi) {
3750 if (mMultiPlatformParam.Uqi.HexNum > 0) {
3751 continue;
3752 }
3753 //
3754 // Read size of UQI string
3755 //
3756 if (AsciiOrUcs2 == ASCII) {
3757 fscanf(ScriptFile, " %x", (INT32 *)&mMultiPlatformParam.Uqi.HexNum);
3758 } else {
3759 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3760 if (Char8Str == NULL) {
3761 return EFI_ABORTED;
3762 }
3763 sscanf(Char8Str, " %x", (INT32 *)&mMultiPlatformParam.Uqi.HexNum);
3764 if (Char8Str != NULL) {
3765 free (Char8Str);
3766 Char8Str = NULL;
3767 }
3768 }
3769 if (mMultiPlatformParam.Uqi.HexNum > MAX_INPUT_ALLOCATE_SIZE) {
3770 return EFI_ABORTED;
3771 }
3772 //
3773 // Malloc buffer for string size + null termination
3774 //
3775 if (mMultiPlatformParam.Uqi.Data != NULL) {
3776 free (mMultiPlatformParam.Uqi.Data);
3777 mMultiPlatformParam.Uqi.Data = NULL;
3778 }
3779 mMultiPlatformParam.Uqi.Data = (CHAR16 *)calloc(mMultiPlatformParam.Uqi.HexNum + 1, sizeof(CHAR16));
3780
3781 if (mMultiPlatformParam.Uqi.Data == NULL) {
3782 printf("Error. Unable to allocate 0x%04zx bytes for UQI string -- FAILURE\n", (mMultiPlatformParam.Uqi.HexNum + 1) * sizeof(CHAR16));
3783 break;
3784 }
3785 //
3786 // Read UQI string
3787 //
3788 for (Index = 0; Index < mMultiPlatformParam.Uqi.HexNum; Index++) {
3789 if (AsciiOrUcs2 == ASCII) {
3790 fscanf(ScriptFile, " %hx", (short *)&(mMultiPlatformParam.Uqi.Data[Index]));
3791 } else {
3792 Char8Str = ReadUcs2ToStr (ScriptFile, AsciiOrUcs2);
3793 if (Char8Str == NULL) {
3794 return EFI_ABORTED;
3795 }
3796 sscanf(Char8Str, " %hx", (short *)&(mMultiPlatformParam.Uqi.Data[Index]));
3797 if (Char8Str != NULL) {
3798 free (Char8Str);
3799 Char8Str = NULL;
3800 }
3801 }
3802 }
3803 //
3804 // Set null termination
3805 //
3806 mMultiPlatformParam.Uqi.Data[Index] = 0;
3807 ReadPlatformIdUqi = FALSE;
3808 }
3809
3810 } while((TempChar != '\n') && !feof(ScriptFile));
3811 break;
3812 //
3813 // To do: Get and set DefaultId and PlatformId here!
3814 //
3815 default:
3816 //
3817 // Comment or garbage, skip to next line
3818 //
3819 do {
3820 if (AsciiOrUcs2 == ASCII) {
3821 fread(&TempChar, sizeof (CHAR8), 1, ScriptFile);
3822 } else {
3823 fread(&TempChar16, sizeof (CHAR16), 1, ScriptFile);
3824 if (AsciiOrUcs2 == BIG_UCS2) {
3825 TempChar = (CHAR8)TempChar16;
3826 } else {
3827 TempChar = (CHAR8)(TempChar16 >> 8);
3828 }
3829 }
3830 } while((TempChar != '\n') && !feof(ScriptFile));
3831 break;
3832 }
3833 }
3834 return EFI_SUCCESS;
3835 }
3836
3837 /**
3838 Get the offset of file name from the whole path.
3839
3840 @param NameStr The whole file path.
3841
3842 @retval Offset Return the offset of file name in path
3843 **/
3844 static
3845 UINTN
3846 GetOffsetOfFileName (
3847 IN CHAR8 *NameStr
3848 )
3849 {
3850 CHAR8 *Str;
3851 UINTN Index;
3852 UINTN CurIndex;
3853
3854 Index = 0;
3855 CurIndex = 0;
3856 Str = NameStr;
3857
3858 if (NameStr == NULL) {
3859 return 0;
3860 }
3861 while (*Str != '\0') {
3862 if (*Str == OS_SEP) {
3863 CurIndex = Index;
3864 }
3865 Str++;
3866 Index++;
3867 }
3868 if (*(NameStr + CurIndex) == OS_SEP) {
3869 return CurIndex + 1;
3870 } else {
3871 return 0;
3872 }
3873 }
3874 /**
3875 Print the questions which is updated to the current platform successfully.
3876
3877 Parse the Uqi List, and print it till break NULL.
3878
3879 @param List Pointer to a List.
3880
3881 @retval EFI_SUCCESS The Print was complete successfully
3882 @return EFI_ABORTED An error occurred
3883 **/
3884 static
3885 VOID
3886 PrintUpdateListInfo (
3887 IN UQI_PARAM_LIST *UqiList
3888 )
3889 {
3890 UINT32 Index;
3891 UINT32 Index1;
3892 UINT32 Index2;
3893 UQI_PARAM_LIST *CurList;
3894
3895 Index1 = 0;
3896 Index2 = 0;
3897 Index = 0;
3898 CurList = UqiList;
3899
3900 printf ("\n\n -- Update List -- ");
3901
3902 while (CurList != NULL) {
3903 if (!CurList->ErrorOrNot && CurList->ParseOrNot && !CurList->SameOrNot) {
3904 ++Index;
3905 printf ("\n\n[Script line %d] Update No.%d:\n", CurList->Header.ScriptsLine, ++Index1);
3906 printf ("Q %04x ", CurList->Header.HexNum);
3907 for (Index2 = 0; Index2 < CurList->Header.HexNum; Index2++) {
3908 printf ("%04x ", CurList->Header.Data[Index2]);
3909 }
3910 if (CurList->Header.Type == ORDERED_LIST) {
3911 printf ("ORDERED_LIST ");
3912 } else if (CurList->Header.Type == CHECKBOX) {
3913 printf ("CHECKBOX ");
3914 } else if (CurList->Header.Type == ONE_OF) {
3915 printf ("ONE_OF ");
3916 } else if (CurList->Header.Type == NUMERIC) {
3917 printf ("NUMERIC ");
3918 } else if (CurList->Header.Type == STRING) {
3919 printf ("STRING ");
3920 } else {
3921 printf ("UNKNOWN ");
3922 }
3923 //
3924 //Print the value of scripts
3925 //
3926 printf ("\n[ Update Value From: ");
3927 if (CurList->Header.Type == ORDERED_LIST) {
3928 for (Index2 = 0; Index2 <= *(CurList->Header.DiffValue); Index2++) {
3929 printf ("%02x ", *(CurList->Header.DiffValue + Index2));
3930 }
3931 } else if (CurList->Header.Type == STRING) {
3932 printf("\"");
3933 WriteUnicodeStr((CHAR16 *)CurList->Header.DiffValue);
3934 printf("\"");
3935 } else {
3936 printf ("%llx ", *(unsigned long long*)(UINT64 *)CurList->Header.DiffValue);
3937 }
3938 //
3939 //Print the value of current platform
3940 //
3941 printf (" To: ");
3942 if (CurList->Header.Type == ORDERED_LIST) {
3943 for (Index2 = 0; Index2 <= *(CurList->Header.Value); Index2++) {
3944 printf ("%02x ", *(CurList->Header.Value + Index2));
3945 }
3946 } else if (CurList->Header.Type == STRING) {
3947 printf("\"");
3948 WriteUnicodeStr((CHAR16 *)CurList->Header.Value);
3949 printf("\"");
3950 } else {
3951 printf ("%llx ", *(unsigned long long*)(UINT64 *)CurList->Header.Value);
3952 }
3953 printf ("]");
3954 }
3955 CurList = CurList->Next;
3956 }
3957 if (Index > 1) {
3958 printf ("\n\n\n[Results]: %d questions have been updated successfully in total. \n", Index);
3959 } else {
3960 printf ("\n\n\n[Results]: %d question has been updated successfully in total. \n", Index);
3961 }
3962 }
3963
3964
3965 /**
3966 Print the error, when update questions.
3967
3968 Parse the Uqi List, and print it till break NULL.
3969
3970 @param List The Pointer to a List.
3971
3972 **/
3973 static
3974 BOOLEAN
3975 PrintErrorInfo (
3976 IN UQI_PARAM_LIST *UqiList
3977 )
3978 {
3979 UINT32 Index1;
3980 UINT32 Index2;
3981 UINT32 Index;
3982 UQI_PARAM_LIST *CurList;
3983 BOOLEAN IsError;
3984
3985 Index1 = 0;
3986 Index2 = 0;
3987 Index = 0;
3988 CurList = UqiList;
3989 IsError = FALSE;
3990
3991 while (CurList != NULL) {
3992 if (CurList->ErrorOrNot && CurList->ParseOrNot) {
3993 IsError = TRUE;
3994 ++Index;
3995 printf ("\n\n[Script line %d] Error Information No.%d:\n", CurList->Header.ScriptsLine, ++Index1);
3996 printf ("Q %04x ", CurList->Header.HexNum);
3997 for (Index2 = 0; Index2 < CurList->Header.HexNum; Index2++) {
3998 printf ("%04x ", CurList->Header.Data[Index2]);
3999 }
4000 if (CurList->Header.Type == ORDERED_LIST) {
4001 printf ("ORDERED_LIST ");
4002 } else if (CurList->Header.Type == CHECKBOX) {
4003 printf ("CHECKBOX ");
4004 } else if (CurList->Header.Type == ONE_OF) {
4005 printf ("ONE_OF ");
4006 } else if (CurList->Header.Type == NUMERIC) {
4007 printf ("NUMERIC ");
4008 } else if (CurList->Header.Type == STRING) {
4009 printf ("STRING ");
4010 } else {
4011 printf ("UNKNOWN ");
4012 }
4013 //
4014 //Print the Input value of scripts
4015 //
4016 if (CurList->Header.Type == ORDERED_LIST) {
4017 for (Index2 = 0; Index2 <= *CurList->Header.Value; Index2++) {
4018 printf ("%02x ", *(CurList->Header.Value + Index2));
4019 }
4020 } else if (CurList->Header.Type == STRING) {
4021 printf("\"");
4022 WriteUnicodeStr((CHAR16 *)CurList->Header.Value);
4023 printf("\"");
4024 } else {
4025 printf ("%llx ", *(unsigned long long*)(UINT64 *)CurList->Header.Value);
4026 }
4027 //
4028 //Print the Error information
4029 //
4030 if (CurList->Error != NULL) {
4031 printf ("\n%s ", CurList->Error);
4032 }
4033 }
4034 CurList = CurList->Next;
4035 }
4036 if (IsError) {
4037 if (Index > 1) {
4038 printf ("\n\n[Results]: Occurred %d errors during the update process. \n", Index);
4039 } else {
4040 printf ("\n\n[Results]: Occurred %d error during the update process. \n", Index);
4041 }
4042 }
4043 return IsError;
4044 }
4045
4046 /**
4047 Any questions that exist in both the script and the current platform and have
4048 different values will be logged to the screen.
4049
4050 Parse the Uqi List, and print it till break NULL.
4051
4052 @param List Pointer to a List.
4053
4054 @retval EFI_SUCCESS The Print was complete successfully
4055 @return EFI_ABORTED An error occurreds
4056 **/
4057 static
4058 VOID
4059 PrintVerifiedListInfo (
4060 IN UQI_PARAM_LIST *UqiList
4061 )
4062 {
4063 UINT32 Index1;
4064 UINT32 Index2;
4065 UINT32 Index3;
4066 UINT32 Index;
4067 UQI_PARAM_LIST *CurList;
4068 UINT32 StrLen;
4069 UINT32 StrLen1;
4070 UINT32 StrLen2;
4071
4072 Index1 = 0;
4073 Index2 = 0;
4074 Index = 0;
4075 StrLen = 0;
4076 CurList = UqiList;
4077
4078 StrLen1 = strlen (mSetupTxtName + GetOffsetOfFileName (mSetupTxtName));
4079 StrLen2 = strlen (mInputFdName + GetOffsetOfFileName (mInputFdName));
4080
4081 StrLen = (StrLen1 > StrLen2) ? StrLen1:StrLen2;
4082
4083 printf ("\n\n -- Different List -- ");
4084
4085 while (CurList != NULL) {
4086 if (!CurList->SameOrNot && CurList->ParseOrNot) {
4087 ++Index;
4088 printf ("\n\n[Script line %d] Difference No.%d:", CurList->Header.ScriptsLine, ++Index1);
4089 printf ("\n[%s", mSetupTxtName + GetOffsetOfFileName (mSetupTxtName));
4090 for (Index3 = 0; Index3 < StrLen - StrLen1; Index3++) {
4091 printf (" ");
4092 }
4093 printf ("]:");
4094 printf (" Q %04x ", CurList->Header.HexNum);
4095 for (Index2 = 0; Index2 < CurList->Header.HexNum; Index2++) {
4096 printf ("%04x ", CurList->Header.Data[Index2]);
4097 }
4098 if (CurList->Header.Type == ORDERED_LIST) {
4099 printf ("ORDERED_LIST ");
4100 } else if (CurList->Header.Type == CHECKBOX) {
4101 printf ("CHECKBOX ");
4102 } else if (CurList->Header.Type == ONE_OF) {
4103 printf ("ONE_OF ");
4104 } else if (CurList->Header.Type == NUMERIC) {
4105 printf ("NUMERIC ");
4106 } else if (CurList->Header.Type == STRING) {
4107 printf ("STRING ");
4108 } else {
4109 printf ("UNKNOWN ");
4110 }
4111 //
4112 //Print the Input value of scripts
4113 //
4114 if (CurList->Header.Type == ORDERED_LIST) {
4115 for (Index2 = 0; Index2 <= *(CurList->Header.Value); Index2++) {
4116 printf ("%02x ", *(CurList->Header.Value + Index2));
4117 }
4118 } else if (CurList->Header.Type == STRING) {
4119 printf("\"");
4120 WriteUnicodeStr((CHAR16 *)CurList->Header.Value);
4121 printf("\"");
4122 } else {
4123 printf ("%llx ", *(unsigned long long*)(UINT64 *)CurList->Header.Value);
4124 }
4125 //
4126 //Print the value of current platform
4127 //
4128 printf ("\n[%s", mInputFdName + GetOffsetOfFileName (mInputFdName));
4129 for (Index3 = 0; Index3 < StrLen - StrLen2; Index3++) {
4130 printf (" ");
4131 }
4132 printf ("]:");
4133 printf (" Q %04x ", CurList->Header.HexNum);
4134 for (Index2 = 0; Index2 < CurList->Header.HexNum; Index2++) {
4135 printf ("%04x ", CurList->Header.Data[Index2]);
4136 }
4137 if (CurList->Header.Type == ORDERED_LIST) {
4138 printf ("ORDERED_LIST ");
4139 } else if (CurList->Header.Type == CHECKBOX) {
4140 printf ("CHECKBOX ");
4141 } else if (CurList->Header.Type == ONE_OF) {
4142 printf ("ONE_OF ");
4143 } else if (CurList->Header.Type == NUMERIC) {
4144 printf ("NUMERIC ");
4145 } else if (CurList->Header.Type == STRING) {
4146 printf ("STRING ");
4147 } else {
4148 printf ("UNKNOWN ");
4149 }
4150 if (CurList->Header.Type == ORDERED_LIST) {
4151 for (Index2 = 0; Index2 <= *(CurList->Header.DiffValue); Index2++) {
4152 printf ("%02x ", *(CurList->Header.DiffValue + Index2));
4153 }
4154 } else if (CurList->Header.Type == STRING) {
4155 printf("\"");
4156 WriteUnicodeStr((CHAR16 *)CurList->Header.DiffValue);
4157 printf("\"");
4158 } else {
4159 printf ("%llx ", *(unsigned long long*)(UINT64 *)CurList->Header.DiffValue);
4160 }
4161 }
4162 CurList = CurList->Next;
4163 }
4164 if (Index > 1) {
4165 printf (
4166 "\n\n\n[Results]: There are %d differences between '%s' and '%s' in total.\n\n\n",
4167 Index,
4168 mSetupTxtName + GetOffsetOfFileName (mSetupTxtName),
4169 mInputFdName + GetOffsetOfFileName (mInputFdName)
4170 );
4171 } else {
4172 printf (
4173 "\n\n\n[Results]: There is %d difference between '%s' and '%s' in total.\n\n\n",
4174 Index,
4175 mSetupTxtName + GetOffsetOfFileName (mSetupTxtName),
4176 mInputFdName + GetOffsetOfFileName (mInputFdName)
4177 );
4178 }
4179 }
4180
4181 /**
4182 Insert Uqi object to the end of unidirection List.
4183
4184 @param InList The Pointer to the current object
4185 @param UqiListEntry The pointer to the entry of UqiList
4186
4187 @return EFI_SUCCESS
4188 **/
4189 EFI_STATUS
4190 InsertUnidirectionList (
4191 IN UQI_PARAM_LIST *InList,
4192 IN UQI_PARAM_LIST **UqiListEntry
4193 )
4194 {
4195 UQI_PARAM_LIST **UqiCurList;
4196 UQI_PARAM_LIST *UqiNext;
4197
4198 UqiCurList = NULL;
4199 UqiNext = NULL;
4200
4201 if (UqiListEntry == NULL) {
4202 return EFI_ABORTED;
4203 }
4204 //
4205 // Insert to Uqi Node to UqiList
4206 //
4207 UqiCurList = UqiListEntry;
4208 UqiNext = *UqiCurList;
4209 if (UqiNext == NULL) {
4210 //
4211 //Insert is the first node as node header
4212 //
4213 *UqiCurList = InList;
4214 } else {
4215 while ((UqiNext != NULL) && (UqiNext->Next != NULL)) {
4216 UqiNext = UqiNext->Next;
4217 }
4218 UqiNext->Next = InList;
4219 }
4220 return EFI_SUCCESS;
4221 }
4222
4223 /**
4224 Free variable unidirection List.
4225
4226 @param UqiListEntry The pointer to the entry of UqiList
4227
4228 @return EFI_SUCCESS
4229 **/
4230 EFI_STATUS
4231 FreeUnidirectionList (
4232 IN UQI_PARAM_LIST *UqiListEntry
4233 )
4234 {
4235 UQI_PARAM_LIST *Next;
4236
4237 Next = NULL;
4238 //
4239 // Free Uqi List
4240 //
4241 while (UqiListEntry != NULL) {
4242 Next = UqiListEntry->Next;
4243 if (UqiListEntry->Header.Value != NULL) {
4244 free (UqiListEntry->Header.Value);
4245 }
4246 if (UqiListEntry->Header.DiffValue != NULL) {
4247 free (UqiListEntry->Header.DiffValue);
4248 }
4249 if (UqiListEntry->Header.Data != NULL) {
4250 free (UqiListEntry->Header.Data);
4251 }
4252 if (UqiListEntry->Header.DefaultId != NULL) {
4253 free (UqiListEntry->Header.DefaultId);
4254 }
4255 if (UqiListEntry->Header.PlatformId != NULL) {
4256 free (UqiListEntry->Header.PlatformId);
4257 }
4258 if (UqiListEntry->Error != NULL) {
4259 free (UqiListEntry->Error);
4260 }
4261 free (UqiListEntry);
4262 UqiListEntry = Next;
4263 }
4264
4265 return EFI_SUCCESS;
4266 }
4267
4268 /**
4269 Delete a directory and files in it.
4270
4271 @param DirName Name of the directory need to be deleted.
4272
4273 @return EFI_INVALID_PARAMETER
4274 @return EFI_SUCCESS
4275 **/
4276 static
4277 EFI_STATUS
4278 LibRmDir (
4279 IN CHAR8* DirName
4280 )
4281 {
4282 CHAR8* SystemCommand;
4283
4284 SystemCommand = NULL;
4285
4286 if (DirName == NULL) {
4287 return EFI_INVALID_PARAMETER;
4288 }
4289
4290 //
4291 // Delete a directory and files in it.
4292 //
4293
4294 SystemCommand = malloc (
4295 strlen (RMDIR_STR) +
4296 strlen (DirName) +
4297 1
4298 );
4299 if (SystemCommand == NULL) {
4300 return EFI_OUT_OF_RESOURCES;
4301 }
4302
4303 sprintf (
4304 SystemCommand,
4305 RMDIR_STR,
4306 DirName
4307 );
4308
4309 system (SystemCommand);
4310 free(SystemCommand);
4311
4312 return EFI_SUCCESS;
4313 }
4314
4315 /**
4316 Pick up the FFS from the FD image.
4317
4318 Call BfmLib to get all FFS in one FD image, and save all which includes IFR
4319 Binary to gEfiFdInfo structure.
4320
4321 @retval EFI_SUCCESS Get the address successfully.
4322 **/
4323 static
4324 EFI_STATUS
4325 PickUpFfsFromFd (
4326 VOID
4327 )
4328 {
4329 CHAR8 *SystemCommandFormatString;
4330 CHAR8 *SystemCommand;
4331 CHAR8 *TempSystemCommand;
4332 CHAR8 *TemDir;
4333 EFI_STATUS Status;
4334 INT32 ReturnValue;
4335
4336 Status = EFI_SUCCESS;
4337 SystemCommandFormatString = NULL;
4338 SystemCommand = NULL;
4339 TempSystemCommand = NULL;
4340 TemDir = NULL;
4341 ReturnValue = 0;
4342
4343 memset (&gEfiFdInfo, 0, sizeof (G_EFI_FD_INFO));
4344 //
4345 // Construction 'system' command string
4346 //
4347 SystemCommandFormatString = "BfmLib -e \"%s\" ";
4348
4349 SystemCommand = malloc (
4350 strlen (SystemCommandFormatString) + strlen (mInputFdName) + 1
4351 );
4352
4353 if (SystemCommand == NULL) {
4354 printf ("Fail to allocate memory.\n");
4355 return EFI_ABORTED;
4356 }
4357
4358 sprintf (
4359 SystemCommand,
4360 "BfmLib -e \"%s\" ",
4361 mInputFdName
4362 );
4363
4364 if (mFullGuidToolDefinitionDir[0] != 0) {
4365 TempSystemCommand = SystemCommand;
4366 SystemCommand = malloc (
4367 strlen (mFullGuidToolDefinitionDir) + strlen (OS_SEP_STR) + strlen (TempSystemCommand) + 1
4368 );
4369
4370 if (SystemCommand == NULL) {
4371 free (TempSystemCommand);
4372 return EFI_UNSUPPORTED;
4373 }
4374 strcpy (SystemCommand, mFullGuidToolDefinitionDir);
4375 strcat (SystemCommand, OS_SEP_STR);
4376 strcat (SystemCommand, TempSystemCommand);
4377 free (TempSystemCommand);
4378
4379 }
4380
4381 //
4382 // Call BfmLib to get all FFS in Temp folder of current path
4383 //
4384 ReturnValue = system (SystemCommand);
4385 free (SystemCommand);
4386 if (ReturnValue == -1) {
4387 printf ("Error. Call BfmLib failed.\n");
4388 return EFI_ABORTED;
4389 }
4390 //
4391 //Pick up the FFS which is interrelated with the IFR binary.
4392 //
4393 TemDir = getcwd (NULL, _MAX_PATH);
4394 if (strlen (TemDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME)> _MAX_PATH - 1) {
4395 printf ("The directory is too long \n");
4396 return EFI_ABORTED;
4397 }
4398 strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1);
4399 strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1);
4400 mMultiPlatformParam.ExistStorageFfsInBfv = FALSE;
4401 Status = FindFileInFolder (TemDir, &mMultiPlatformParam.ExistStorageFfsInBfv, &mMultiPlatformParam.SizeOptimized);
4402
4403 return Status;
4404 }
4405
4406 #define BUILD_IN_TOOL_COUNT 4
4407 /**
4408 Generate pre-defined guided tools data.
4409
4410 @return An EFI_HANDLE contain guided tools data.
4411
4412 **/
4413 static
4414 EFI_HANDLE
4415 PreDefinedGuidedTools (
4416 VOID
4417 )
4418 {
4419 EFI_GUID Guid;
4420 STRING_LIST *Tool;
4421 GUID_SEC_TOOL_ENTRY *FirstGuidTool;
4422 GUID_SEC_TOOL_ENTRY *LastGuidTool;
4423 GUID_SEC_TOOL_ENTRY *NewGuidTool;
4424 UINT8 Index;
4425 EFI_STATUS Status;
4426
4427 CHAR8 PreDefinedGuidedTool[BUILD_IN_TOOL_COUNT][255] = {
4428 "a31280ad-481e-41b6-95e8-127f4c984779 TIANO TianoCompress",
4429 "ee4e5898-3914-4259-9d6e-dc7bd79403cf LZMA LzmaCompress",
4430 "fc1bcdb0-7d31-49aa-936a-a4600d9dd083 CRC32 GenCrc32",
4431 "3d532050-5cda-4fd0-879e-0f7f630d5afb BROTLI BrotliCompress"
4432 };
4433
4434 Tool = NULL;
4435 FirstGuidTool = NULL;
4436 LastGuidTool = NULL;
4437 NewGuidTool = NULL;
4438
4439 for (Index = 0; Index < BUILD_IN_TOOL_COUNT; Index++) {
4440 Tool = SplitStringByWhitespace (PreDefinedGuidedTool[Index]);
4441 if ((Tool != NULL) &&
4442 (Tool->Count == 3)
4443 ) {
4444 Status = StringToGuid (Tool->Strings[0], &Guid);
4445 if (!EFI_ERROR (Status)) {
4446 NewGuidTool = malloc (sizeof (GUID_SEC_TOOL_ENTRY));
4447 if (NewGuidTool != NULL) {
4448 memcpy (&(NewGuidTool->Guid), &Guid, sizeof (Guid));
4449 NewGuidTool->Name = CloneString(Tool->Strings[1]);
4450 NewGuidTool->Path = CloneString(Tool->Strings[2]);
4451 NewGuidTool->Next = NULL;
4452 } else {
4453 printf ( "Fail to allocate memory. \n");
4454 if (Tool != NULL) {
4455 FreeStringList (Tool);
4456 }
4457 return NULL;
4458 }
4459 if (FirstGuidTool == NULL) {
4460 FirstGuidTool = NewGuidTool;
4461 } else {
4462 LastGuidTool->Next = NewGuidTool;
4463 }
4464 LastGuidTool = NewGuidTool;
4465 }
4466
4467 } else {
4468 fprintf (stdout, "Error");
4469 }
4470 if (Tool != NULL) {
4471 FreeStringList (Tool);
4472 Tool = NULL;
4473 }
4474 }
4475 return FirstGuidTool;
4476 }
4477
4478 /**
4479 Read all storages under a specified platformId and defaultId from BFV.
4480
4481 @param Binary The pointer to the buffer of binary.
4482 @param StorageListEntry The pointer to the storage list.
4483
4484 @return length The length of storage
4485 **/
4486 UINT32
4487 ReadStorageFromBinary (
4488 IN UINT8 *Binary,
4489 IN LIST_ENTRY *StorageListEntry
4490 )
4491 {
4492 UINT32 Length;
4493 UINT8 *DataBase;
4494 BOOLEAN AuthencitatedMonotonicOrNot;
4495 BOOLEAN AuthencitatedBasedTimeOrNot;
4496
4497 Length = 0;
4498 AuthencitatedMonotonicOrNot = FALSE;
4499 AuthencitatedBasedTimeOrNot = FALSE;
4500 DataBase = Binary + sizeof (EFI_COMMON_SECTION_HEADER);
4501 //
4502 // Judge the layout of NV by Variable Guid
4503 //
4504 AuthencitatedMonotonicOrNot = CheckMonotonicBasedVarStore ((VOID *)(DataBase + *(UINT16 *)DataBase));
4505 AuthencitatedBasedTimeOrNot = CheckTimeBasedVarStoreOrNot ((VOID *)(DataBase + *(UINT16 *)DataBase));
4506
4507 if (AuthencitatedMonotonicOrNot) {
4508 //
4509 // Read variable with Monotonic based layout from binary
4510 //
4511 Length = ReadMonotonicBasedVariableToList (Binary, StorageListEntry);
4512 } else if (AuthencitatedBasedTimeOrNot){
4513 //
4514 // Read variable with time-based layout from binary
4515 //
4516 Length = ReadTimeBasedVariableToList (Binary, StorageListEntry);
4517 } else {
4518 //
4519 // Read variable with normal layout from binary
4520 //
4521 Length = ReadVariableToList (Binary, StorageListEntry);
4522 }
4523
4524 return Length;
4525 }
4526
4527 /**
4528 Insert one storage to the raw bianry, and return its length.
4529
4530 @param Storage The pointer to a storage in storage list.
4531 @param Binary The pointer to the buffer of binary.
4532
4533 @return length The length of storage
4534 **/
4535 UINT32
4536 PutStorageToBinary (
4537 IN FORMSET_STORAGE *Storage,
4538 IN UINT8 *Binary,
4539 IN LIST_ENTRY *StorageListEntry
4540 )
4541 {
4542 EFI_FIRMWARE_VOLUME_HEADER *VarAddr;
4543 UINT32 Length;
4544 UINT32 Index;
4545 UINT8 *BinaryBeginning;
4546 FORMSET_STORAGE *CurStorage;
4547 LIST_ENTRY *StorageLink;
4548 VOID *VariableStoreHeader;
4549 BOOLEAN AuthencitatedMonotonicOrNot;
4550 BOOLEAN AuthencitatedBasedTimeOrNot;
4551
4552 VarAddr = (EFI_FIRMWARE_VOLUME_HEADER *) gEfiFdInfo.EfiVariableAddr;
4553 Length = 0;
4554 Index = 0;
4555 BinaryBeginning = Binary;
4556 VariableStoreHeader = (VOID *)((CHAR8 *)VarAddr + VarAddr->HeaderLength);
4557 AuthencitatedMonotonicOrNot = FALSE;
4558 AuthencitatedBasedTimeOrNot = FALSE;
4559 //
4560 // Judge the layout of NV by gEfiVariableGuid
4561 //
4562 AuthencitatedMonotonicOrNot = CheckMonotonicBasedVarStore (VariableStoreHeader);
4563 AuthencitatedBasedTimeOrNot = CheckTimeBasedVarStoreOrNot (VariableStoreHeader);
4564 //
4565 // Build the binary for BFV
4566 //
4567 StorageLink = GetFirstNode (StorageListEntry);
4568
4569 while (!IsNull (StorageListEntry, StorageLink)) {
4570 CurStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);
4571 if ((CurStorage->DefaultId[0] == Storage->DefaultId[0])
4572 && (CurStorage->PlatformId[0] == Storage->PlatformId[0])
4573 && !CurStorage->Skip
4574 ) {
4575 CurStorage->Skip = TRUE;
4576
4577 if (AuthencitatedMonotonicOrNot) {
4578 //
4579 // Copy variable with Monotonic based layout to binary
4580 //
4581 Length = CopyMonotonicBasedVariableToBinary (CurStorage, BinaryBeginning, Index);
4582 } else if (AuthencitatedBasedTimeOrNot){
4583 //
4584 // Copy variable with time-based layout to binary
4585 //
4586 Length = CopyTimeBasedVariableToBinary (CurStorage, BinaryBeginning, Index);
4587 } else {
4588 //
4589 // Copy variable with normall layout to binary
4590 //
4591 Length = CopyVariableToBinary (CurStorage, BinaryBeginning, Index);
4592 }
4593 Index++;
4594 }
4595 StorageLink = GetNextNode (StorageListEntry, StorageLink);
4596 }
4597 //
4598 // Fix the length of storage header under a specified DefaultId and PlatformId
4599 //
4600 if (AuthencitatedMonotonicOrNot) {
4601 FixMontonicVariableHeaderSize (BinaryBeginning, Length);
4602 } else if (AuthencitatedBasedTimeOrNot){
4603 FixBasedTimeVariableHeaderSize (BinaryBeginning, Length);
4604 } else {
4605 FixVariableHeaderSize (BinaryBeginning, Length);
4606 }
4607 return Length;
4608 }
4609
4610 /**
4611 Insert one storage to Fd's NvStoreDatabase, and return its length.
4612
4613 @param Storage The pointer to a storage in storage list.
4614 @param Binary The pointer to the buffer of binary.
4615
4616 @return length The length of storage
4617 **/
4618 UINT32
4619 PutStorageToNvStoreBinary (
4620 IN FORMSET_STORAGE *Storage,
4621 IN UINT8 *Binary,
4622 IN LIST_ENTRY *StorageListEntry
4623 )
4624 {
4625 UINT32 Length;
4626 UINT32 Index;
4627 UINT8 *BinaryBeginning;
4628 FORMSET_STORAGE *CurStorage;
4629 LIST_ENTRY *StorageLink;
4630
4631 Length = 0;
4632 Index = 0;
4633 BinaryBeginning = Binary;
4634 //
4635 // Build the binary for NvStorDatabase
4636 //
4637 StorageLink = GetFirstNode (StorageListEntry);
4638 while (!IsNull (StorageListEntry, StorageLink)) {
4639 CurStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);
4640 if ((CurStorage->PlatformId[0] == Storage->PlatformId[0])
4641 && (CurStorage->DefaultId[0] == Storage->DefaultId[0])
4642 && !CurStorage->Skip
4643 ) {
4644 CurStorage->Skip = TRUE;
4645 Length = CopyVariableToNvStoreBinary (CurStorage, BinaryBeginning, Index);
4646 Index++;
4647 }
4648 StorageLink = GetNextNode (StorageListEntry, StorageLink);
4649 }
4650 // Alignment
4651 Length = (Length + 3) & ~3;
4652 FixNvStoreVariableHeaderSize (BinaryBeginning, Length);
4653 return Length;
4654 }
4655
4656 /**
4657 Optimize the Delta binary size based on the default setting binary, and
4658 create a new binary with new size on the Storage.ffs.
4659
4660 @param DefaultBinary The pointer to a default setting binary
4661 @param DefaultHeaderLen The header lenght of default setting binary
4662 @param DeltaBinary The pointer to a delta setting binary
4663 @param CurrentSize The size of current delta data.
4664
4665 @return length The length of new storage
4666 **/
4667 UINT32
4668 OptimizeStorageDeltaData (
4669 IN UINT8 *DefaultBinary,
4670 IN UINT8 *CurrentBinary,
4671 IN OUT UINT8 *DeltaBinary,
4672 IN UINT32 CurrentSize
4673 )
4674 {
4675 UINT32 Size;
4676 UINT16 Index;
4677 UINT32 DefaultHeaderSize;
4678 UINT32 DeltaHeaderSize;
4679 UINT32 AlignSize;
4680 PCD_DATA_DELTA DeltaData;
4681 DefaultHeaderSize = ((PCD_DEFAULT_DATA *)DefaultBinary)->HeaderSize + 4;
4682 DeltaHeaderSize = ((PCD_DEFAULT_DATA *)CurrentBinary)->HeaderSize + 4;
4683 //
4684 // Copy the Delta Header directly
4685 //
4686 Size = DeltaHeaderSize;
4687 memcpy (DeltaBinary, CurrentBinary, Size);
4688 //
4689 // Compare the delta data and optimize the size
4690 //
4691 for (Index = 0; Index < CurrentSize - DeltaHeaderSize; Index++) {
4692 if (*(DefaultBinary + DefaultHeaderSize + Index) != *(CurrentBinary + DeltaHeaderSize + Index)) {
4693 DeltaData.Offset = Index;
4694 DeltaData.Value = *(CurrentBinary + DeltaHeaderSize + Index);
4695 memcpy (DeltaBinary + Size, &DeltaData, sizeof (DeltaData));
4696 Size = Size + sizeof(DeltaData);
4697 }
4698 }
4699 *(UINT32 *)DeltaBinary = Size;
4700 AlignSize = (Size + 7) & ~7;
4701 //set Alignment data 0x00
4702 for (Index = 0; Index < AlignSize - Size; Index++){
4703 *(DeltaBinary + Size + Index) = 0x0;
4704 }
4705 return Size;
4706 }
4707
4708 /**
4709 Optimize the Delta binary size based on the default setting binary, and
4710 create a new binary with new size on the Storage.ffs.
4711
4712 @param DefaultBinary The pointer to a default setting binary
4713 @param DefaultHeaderLen The header lenght of default setting binary
4714 @param DeltaBinary The pointer to a delta setting binary
4715 @param CurrentSize The size of current delta data.
4716
4717 @return length The length of new storage
4718 **/
4719 UINT32
4720 OptimizeStorageSection (
4721 IN UINT8 *DefaultBinary,
4722 IN UINT8 *CurrentBinary,
4723 IN OUT UINT8 *DeltaBinary,
4724 IN UINT32 CurrentSize
4725 )
4726 {
4727 UINT32 Size;
4728 UINT16 Index;
4729 UINT32 DefaultHeaderSize;
4730 UINT32 DeltaHeaderSize;
4731 DATA_DELTA DeltaData;
4732
4733 DefaultHeaderSize = *(UINT16 *)DefaultBinary;
4734 DeltaHeaderSize = *(UINT16 *)CurrentBinary;
4735
4736 //
4737 // Copy the Delta Header directly
4738 //
4739 Size = DeltaHeaderSize;
4740 memcpy (DeltaBinary, CurrentBinary, Size);
4741 //
4742 // Compare the delta data and optimize the size
4743 //
4744 for (Index = 0; Index < CurrentSize - DeltaHeaderSize; Index++) {
4745 if (*(DefaultBinary + DefaultHeaderSize + Index) != *(CurrentBinary + DeltaHeaderSize + Index)) {
4746 DeltaData.Offset = Index;
4747 DeltaData.Value = *(CurrentBinary + DeltaHeaderSize + Index);
4748 memcpy (DeltaBinary + Size, &DeltaData, sizeof (DeltaData));
4749 Size = Size + sizeof(DeltaData);
4750 }
4751 }
4752 return Size;
4753 }
4754
4755 /**
4756 Create the storage section and copy it to memory.
4757
4758 @param Buffer The pointer to the buffer
4759 @param Size The size of input buffer.
4760
4761 @return the new size
4762 **/
4763 UINT32
4764 CreateStorageSection (
4765 IN OUT UINT8 *Buffer,
4766 IN UINT32 Size,
4767 IN CHAR8 *FileName
4768 )
4769 {
4770 FILE *BinaryFd;
4771 UINTN BytesWrite;
4772 UINT32 SectionSize;
4773
4774 BinaryFd = NULL;
4775 //
4776 // Create the raw section files in FFS
4777 //
4778 BinaryFd = fopen (FileName, "wb+");
4779 if (BinaryFd == NULL) {
4780 printf ("Error. Failed to create the raw data section.\n");
4781 return 0;
4782 }
4783 fseek (BinaryFd, 0, SEEK_SET);
4784 BytesWrite = fwrite (Buffer, sizeof (CHAR8), Size, BinaryFd);
4785 fclose (BinaryFd);
4786 if (BytesWrite != Size) {
4787 printf ("Error. Failed to write the raw data section.\n");
4788 return 0;
4789 }
4790 CreateRawSection (FileName, FileName);
4791
4792 BinaryFd = fopen (FileName, "rb");
4793 if (BinaryFd == NULL) {
4794 printf ("Error. Failed to open the raw data section.\n");
4795 return 0;
4796 }
4797 fseek (BinaryFd, 0, SEEK_SET);
4798 BytesWrite = fread (Buffer, sizeof (CHAR8), (Size + sizeof (EFI_COMMON_SECTION_HEADER)), BinaryFd);
4799 fclose (BinaryFd);
4800 if (BytesWrite != (Size + sizeof (EFI_COMMON_SECTION_HEADER))) {
4801 printf ("Error. Failed to read the raw data section.\n");
4802 return 0;
4803 }
4804
4805 SectionSize = FvBufExpand3ByteSize (((EFI_COMMON_SECTION_HEADER *)Buffer)->Size);
4806 return SectionSize;
4807 }
4808
4809 /**
4810 Read NvStoreDataBase and insert it to the Storage list.
4811
4812 @param InputFdName The pointer to the input fd name.
4813 @param VarListEntry The pointer to the variable list.
4814
4815 @return EFI_INVALID_PARAMETER
4816 @return EFI_SUCCESS
4817 **/
4818 EFI_STATUS
4819 ReadStorageFromNvStoreDatabase (
4820 IN LIST_ENTRY *VarListEntry
4821 )
4822 {
4823
4824 UINT8 *Binary;
4825 UINT8 *FullBinary;
4826 UINT8 *VarDataBinary;
4827 UINT8 *PreVarDataBinary;
4828 UINT8 *DataBase;
4829 PCD_DEFAULT_DATA *DeltaVarStoreHeader;
4830 PCD_DEFAULT_DATA *PrePcdDefaultData;
4831 UINT8 *DeltaData;
4832 UINT32 DeltaSize;
4833 UINT32 DataSize;
4834 UINT32 HeaderSize;
4835 UINT32 BinaryLength;
4836 UINT32 Size;
4837 UINT32 PreVarDataSize;
4838 PCD_NV_STORE_DEFAULT_BUFFER_HEADER *NvStoreHeader;
4839 UINT32 Offset;
4840 UINT32 Value;
4841 UINT32 Index;
4842
4843 BinaryLength = 0;
4844 Binary = NULL;
4845 FullBinary = NULL;
4846 DataBase = NULL;
4847 DeltaVarStoreHeader = NULL;
4848 PreVarDataBinary = NULL;
4849 PreVarDataSize = 0;
4850 DeltaSize = 0;
4851 Size = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER);
4852 VarDataBinary = NULL;
4853
4854 //
4855 // Check whether the FD has included the storage FFS
4856 //
4857 //if (!mMultiPlatformParam.ExistStorageFfsInBfv) {
4858 // return EFI_ABORTED;
4859 //}
4860 NvStoreHeader = (PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)gEfiFdInfo.NvStoreDatabase;
4861 BinaryLength = NvStoreHeader->Length;
4862 Binary = (UINT8 *)gEfiFdInfo.NvStoreDatabase;
4863 //
4864 // If detect size optimized format, transfer it to normal format
4865 // before parse it
4866 //
4867 if (mMultiPlatformParam.SizeOptimized) {
4868 FullBinary = calloc(gEfiFdInfo.FdSize, sizeof(UINT8));
4869 if (FullBinary == NULL) {
4870 printf ("Error. Memory allocation failed.\n");
4871 return EFI_ABORTED;
4872 }
4873 }
4874 while (Size < BinaryLength) {
4875 DataBase = Binary + Size;
4876 DataSize = *(UINT32 *)DataBase;
4877 if (Size == sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
4878 PrePcdDefaultData = (PCD_DEFAULT_DATA *) DataBase;
4879 HeaderSize = PrePcdDefaultData->HeaderSize;
4880 PreVarDataSize = DataSize - 4 - HeaderSize;
4881 VarDataBinary = malloc(DataSize);
4882 if (VarDataBinary == NULL) {
4883 printf ("Error. Memory allocation failed.\n");
4884 return EFI_ABORTED;
4885 }
4886 memcpy (VarDataBinary, DataBase, DataSize);
4887 PreVarDataBinary = malloc(DataSize - 4 - HeaderSize);
4888 if (PreVarDataBinary == NULL) {
4889 printf ("Error. Memory allocation failed.\n");
4890 return EFI_ABORTED;
4891 }
4892 memcpy (PreVarDataBinary, DataBase + 4 + HeaderSize , DataSize - 4 - HeaderSize);
4893 } else {
4894 DeltaVarStoreHeader = (PCD_DEFAULT_DATA *)DataBase;
4895 DeltaSize = DeltaVarStoreHeader->DataSize;
4896 HeaderSize = DeltaVarStoreHeader->HeaderSize;
4897 DeltaData = (UINT8*) DeltaVarStoreHeader;
4898
4899 VarDataBinary = malloc(PreVarDataSize + HeaderSize + 4);
4900 if (VarDataBinary == NULL) {
4901 printf ("Error. Memory allocation failed.\n");
4902 return EFI_ABORTED;
4903 }
4904 //
4905 // Copy the default setting data
4906 //
4907 memcpy (VarDataBinary, DataBase, HeaderSize + 4);
4908 memcpy (VarDataBinary + HeaderSize + 4, PreVarDataBinary, PreVarDataSize);
4909 //
4910 // Merge the delta data with default setting to get the full delta data
4911 //
4912 for (Index = 0; Index < (DeltaSize - HeaderSize - 4)/sizeof(PCD_DATA_DELTA); Index++) {
4913 Offset = ((PCD_DATA_DELTA *)(DeltaData + HeaderSize + 4 + Index * sizeof(PCD_DATA_DELTA)))->Offset;
4914 Value = ((PCD_DATA_DELTA *)(DeltaData + HeaderSize + 4 + Index * sizeof(PCD_DATA_DELTA)))->Value;
4915 if (*(VarDataBinary + HeaderSize + 4 + Offset) != Value) {
4916 *(VarDataBinary + HeaderSize + 4 + Offset) = (UINT8)Value;
4917 }
4918 }
4919 }
4920 //
4921 // Store the Variable Data to VarListEntry
4922 //
4923
4924 ReadNvStoreVariableToList(VarDataBinary, VarListEntry);
4925 Size += (DataSize + 7) & ~7;
4926 }
4927
4928 if (VarDataBinary != NULL) {
4929 free (VarDataBinary);
4930 }
4931 return EFI_SUCCESS;
4932 }
4933
4934 /**
4935 Read FFS from BFV and insert it to the Storage list.
4936
4937 @param InputFdName The pointer to the input fd name.
4938 @param VarListEntry The pointer to the variable list.
4939
4940 @return EFI_INVALID_PARAMETER
4941 @return EFI_SUCCESS
4942 **/
4943 EFI_STATUS
4944 ReadStorageFromBfv (
4945 IN LIST_ENTRY *VarListEntry
4946 )
4947 {
4948
4949 UINT8 *Binary;
4950 UINT8 *FullBinary;
4951 UINT8 *DataBase;
4952 UINT8 *PreVarStoreHeader;
4953 DATA_DELTA *DeltaVarStoreHeader;
4954 UINT8 *DeltaData;
4955 UINT32 PreDataSize;
4956 UINT32 DeltaSize;
4957 UINT32 BinaryLength;
4958 UINT32 Size;
4959 UINT32 SectionSize;
4960 UINT32 FullSectionLen;
4961 UINT32 FullSectionSize;
4962 EFI_FFS_FILE_HEADER *FfsHeader;
4963 UINT16 Offset;
4964 UINT8 Value;
4965 UINT32 Index;
4966 CHAR8 *SectionName;
4967
4968 BinaryLength = 0;
4969 Binary = NULL;
4970 FullBinary = NULL;
4971 DataBase = NULL;
4972 PreVarStoreHeader = NULL;
4973 DeltaVarStoreHeader = NULL;
4974 PreDataSize = 0;
4975 DeltaSize = 0;
4976 FullSectionSize = 0;
4977 Size = sizeof (EFI_FFS_FILE_HEADER);
4978 FfsHeader = NULL;
4979 FullSectionLen = 0;
4980 SectionName = NULL;
4981
4982 SectionName = getcwd(NULL, _MAX_PATH);
4983 if (strlen (SectionName) + 2 * strlen (OS_SEP_STR) + strlen ("Temp") + strlen ("TempSection.sec") >
4984 _MAX_PATH - 1) {
4985 printf ("Error. The current path is too long.\n");
4986 return EFI_INVALID_PARAMETER;
4987 }
4988
4989 sprintf (SectionName + strlen (SectionName), "%cTemp%cTempSection.sec", OS_SEP, OS_SEP);
4990 //
4991 // Check whether the FD has included the storage FFS
4992 //
4993 if (!mMultiPlatformParam.ExistStorageFfsInBfv) {
4994 return EFI_ABORTED;
4995 }
4996 FfsHeader = (EFI_FFS_FILE_HEADER *)gEfiFdInfo.StorageFfsInBfv;
4997 BinaryLength = FvBufExpand3ByteSize (FfsHeader->Size);
4998 Binary = (UINT8 *)FfsHeader;
4999 //
5000 // If detect size optimized format, transfer it to normal format
5001 // before parse it
5002 //
5003 if (mMultiPlatformParam.SizeOptimized) {
5004 FullBinary = calloc(gEfiFdInfo.FdSize, sizeof(UINT8));
5005 if (FullBinary == NULL) {
5006 printf ("Error. Memory allocation failed.\n");
5007 return EFI_ABORTED;
5008 }
5009 while (Size < BinaryLength) {
5010 SectionSize = FvBufExpand3ByteSize (((EFI_COMMON_SECTION_HEADER *)(Binary + Size))->Size);
5011 DataBase = Binary + Size + sizeof (EFI_COMMON_SECTION_HEADER);
5012 if (Size == sizeof (EFI_FFS_FILE_HEADER)) {
5013 PreVarStoreHeader = DataBase + *(UINT16 *)DataBase;
5014 PreDataSize = SectionSize - (*(UINT16 *)DataBase + sizeof(EFI_COMMON_SECTION_HEADER));
5015 memcpy (FullBinary, DataBase, SectionSize - sizeof(EFI_COMMON_SECTION_HEADER));
5016 FullSectionLen = CreateStorageSection (FullBinary, *(UINT16 *)DataBase + PreDataSize, SectionName);
5017 } else {
5018 DeltaVarStoreHeader = (DATA_DELTA *)(DataBase + *(UINT16 *)DataBase);
5019 DeltaSize = *(UINT16 *)DataBase + PreDataSize;
5020 DeltaData = FullBinary + FullSectionSize + *(UINT16 *)DataBase;
5021 //
5022 // Copy the DefaultId and PlatformId directly
5023 //
5024 memcpy (FullBinary + FullSectionSize, DataBase, *(UINT16 *)DataBase);
5025 //
5026 // Copy the default setting data
5027 //
5028 memcpy (DeltaData, PreVarStoreHeader, PreDataSize);
5029 //
5030 // Merge the delta data with default setting to get the full delta data
5031 //
5032 for (Index = 0; Index < (SectionSize - *(UINT16 *)DataBase - sizeof(EFI_COMMON_SECTION_HEADER))/sizeof(DATA_DELTA); Index++) {
5033 Offset = (DeltaVarStoreHeader + Index)->Offset;
5034 Value = (DeltaVarStoreHeader + Index)->Value;
5035 if (*(DeltaData + Offset) != Value) {
5036 *(DeltaData + Offset) = Value;
5037 }
5038 }
5039 FullSectionLen = CreateStorageSection (FullBinary + FullSectionSize, DeltaSize, SectionName);
5040 }
5041 //
5042 // Store the previous binary information
5043 //
5044 DataBase = FullBinary + FullSectionSize + sizeof (EFI_COMMON_SECTION_HEADER);
5045 PreVarStoreHeader = DataBase + *(UINT16 *)DataBase;
5046
5047 Size += (SectionSize + 3) & ~3;
5048 FullSectionSize += (FullSectionLen + 3) & ~3;;
5049 }
5050 //
5051 // Update to the new size
5052 //
5053 BinaryLength = FullSectionSize;
5054 Binary = FullBinary;
5055 Size = 0;
5056 }
5057
5058 //
5059 // Read the storage from BFV and insert to storage list
5060 //
5061 while (Size < BinaryLength) {
5062 SectionSize = ReadStorageFromBinary ((Binary + Size), VarListEntry);
5063 Size += (SectionSize + 3) & ~3;
5064 }
5065 if (FullBinary != NULL) {
5066 free (FullBinary);
5067 }
5068
5069 return EFI_SUCCESS;
5070 }
5071
5072 #define SIZE_64K 0x10000
5073
5074 /**
5075 Create the storage and insert it to BFV by calling BfmLib.
5076
5077 @param InputFdName The pointer to the input fd name.
5078 @param OutputFdName The pointer to the input fd name.
5079 @param VarListEntry The pointer to the variable list.
5080
5081 @return EFI_INVALID_PARAMETER
5082 @return EFI_SUCCESS
5083 **/
5084 EFI_STATUS
5085 InsertBinaryToBfv (
5086 IN CHAR8 *InputFdName,
5087 IN CHAR8 *OutputFdName,
5088 IN LIST_ENTRY *VarListEntry
5089 )
5090 {
5091 UINT8 *Binary;
5092 UINT8 *PreBinary;
5093 UINT32 BinaryLength;
5094 UINT32 PreBinaryLength;
5095 UINT32 OptimizedBinaryLength;
5096 UINT32 Size;
5097 UINT32 OptimizedSize;
5098 EFI_STATUS Status;
5099 LIST_ENTRY *StorageLink;
5100 FORMSET_STORAGE *Storage;
5101 CHAR8 *SystemCommandFormatString;
5102 CHAR8 *SectionNameFormatString;
5103 CHAR8 *SystemCommand;
5104 CHAR8 *TempSystemCommand;
5105 INT32 ReturnValue;
5106 CHAR8 *FileName;
5107 BOOLEAN SizeOptimizedFlag;
5108 CHAR8 *SectionName[_MAXIMUM_SECTION_FILE_NUM];
5109 UINT32 Index;
5110 CHAR8 *TemDir;
5111 //
5112 // Workaround for static code checkers.
5113 // Ensures the size of 'IndexStr' can hold all the digits of an unsigned
5114 // 32-bit integer.
5115 //
5116 CHAR8 IndexStr[16];
5117
5118 BinaryLength = 0;
5119 PreBinaryLength = 0;
5120 Storage = NULL;
5121 StorageLink = NULL;
5122 Binary = NULL;
5123 PreBinary = NULL;
5124 Size = 0;
5125 OptimizedSize = 0;
5126 Status = EFI_SUCCESS;
5127 SystemCommandFormatString = NULL;
5128 SectionNameFormatString = NULL;
5129 SystemCommand = NULL;
5130 TempSystemCommand = NULL;
5131 SizeOptimizedFlag = FALSE;
5132 Index = 0;
5133 FileName = NULL;
5134
5135 TemDir = getcwd (NULL, _MAX_PATH);
5136 SectionNameFormatString = "%s%cTemp%c%s.sec";
5137
5138 memset (SectionName, 0, _MAXIMUM_SECTION_FILE_NUM * sizeof(CHAR8 *));
5139 FileName = malloc (strlen (TemDir) + 1 + strlen ("Storage.ffs") + 1);
5140 if (FileName == NULL) {
5141 printf ("Error. Memory allocation failed.\n");
5142 Status = EFI_ABORTED;
5143 goto Done;
5144 }
5145 sprintf (FileName, "%s%cStorage.ffs", TemDir, OS_SEP);
5146 //
5147 // Allocate the buffer which is the same with the input FD
5148 //
5149 Binary = malloc (SIZE_64K);
5150 if (Binary == NULL) {
5151 printf ("Error. Memory allocation failed.\n");
5152 Status = EFI_ABORTED;
5153 goto Done;
5154 }
5155 PreBinary = malloc (SIZE_64K);
5156 if (PreBinary == NULL) {
5157 printf ("Error. Memory allocation failed.\n");
5158 Status = EFI_ABORTED;
5159 goto Done;
5160 }
5161 //
5162 // If already existed a Storage.ffs in FD, keep the same format when execute update operation whatever input -a or not -a options.
5163 //
5164 if (mMultiPlatformParam.SizeOptimized
5165 || (!mMultiPlatformParam.ExistStorageFfsInBfv && mMultiPlatformParam.SizeOptimizedParam)
5166 ) {
5167 SizeOptimizedFlag = TRUE;
5168 } else if (mMultiPlatformParam.ExistStorageFfsInBfv && mMultiPlatformParam.SizeOptimizedParam && !mMultiPlatformParam.SizeOptimized) {
5169 printf ("\nWarning. The \"-a\" parameter is ignored.\n");
5170 }
5171 //
5172 // Build the binary for BFV
5173 //
5174 StorageLink = GetFirstNode (VarListEntry);
5175
5176 while (!IsNull (VarListEntry, StorageLink)) {
5177 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
5178 if (!Storage->Skip) {
5179 //
5180 // Assign the section name under the Temp directory
5181 //
5182 sprintf (IndexStr, "%d", Index);
5183 SectionName[Index] = calloc (
5184 strlen (SectionNameFormatString) + strlen (TemDir) + strlen(IndexStr) + 1,
5185 sizeof(CHAR8)
5186 );
5187 if (SectionName[Index] == NULL) {
5188 printf ("Error. Memory allocation failed.\n");
5189 Status = EFI_ABORTED;
5190 goto Done;
5191 }
5192 sprintf (
5193 SectionName[Index],
5194 "%s%cTemp%c%s.sec",
5195 TemDir,
5196 OS_SEP,
5197 OS_SEP,
5198 IndexStr
5199 );
5200 memset(Binary, 0, SIZE_64K);
5201 Size = PutStorageToBinary (Storage, Binary, VarListEntry);
5202 assert (Size < SIZE_64K);
5203 //
5204 // Re-calculate the storage section by size optimization
5205 //
5206 if (PreBinaryLength != 0 && SizeOptimizedFlag) {
5207 OptimizedSize = OptimizeStorageSection (
5208 PreBinary + sizeof (EFI_COMMON_SECTION_HEADER),
5209 Binary,
5210 PreBinary + PreBinaryLength,
5211 Size
5212 );
5213 if (OptimizedSize == 0) {
5214 printf ("Error. Failed to optimize the storage section.\n");
5215 Status = EFI_ABORTED;
5216 goto Done;
5217 }
5218 }
5219 //
5220 // Create the raw section with normal format
5221 //
5222 assert (Size < SIZE_64K - sizeof (EFI_COMMON_SECTION_HEADER));
5223 BinaryLength = CreateStorageSection (Binary, Size, SectionName[Index]);
5224 if (BinaryLength == 0) {
5225 printf ("Error. Failed to create the storage section.\n");
5226 Status = EFI_ABORTED;
5227 goto Done;
5228 }
5229 assert (BinaryLength < SIZE_64K);
5230
5231 //
5232 // Create the raw section with optimized format
5233 //
5234 if (PreBinaryLength != 0 && SizeOptimizedFlag) {
5235 OptimizedBinaryLength = CreateStorageSection (PreBinary + PreBinaryLength, OptimizedSize, SectionName[Index]);
5236 if (OptimizedBinaryLength == 0) {
5237 printf ("Error. Failed to create the storage section.\n");
5238 Status = EFI_ABORTED;
5239 goto Done;
5240 }
5241 }
5242 PreBinaryLength = BinaryLength;
5243 memcpy (PreBinary, Binary, PreBinaryLength);
5244 Index++;
5245 }
5246 StorageLink = GetNextNode (VarListEntry, StorageLink);
5247 }
5248 //
5249 // Create the raw ffs by GenFfs
5250 //
5251 CreateRawFfs (&SectionName[0], FileName, SizeOptimizedFlag);
5252
5253 //
5254 // Call BfmLib to insert this binary into the BFV of FD.
5255 //
5256 //
5257 // Construction 'system' command string
5258 //
5259 if (mMultiPlatformParam.ExistStorageFfsInBfv) {
5260 if (mFvNameGuidString != NULL) {
5261 SystemCommandFormatString = "BfmLib -r \"%s\" \"%s\" \"%s\" -g %s";
5262 SystemCommand = malloc (
5263 strlen (SystemCommandFormatString) + strlen (mInputFdName) + strlen (mOutputFdName) + strlen (FileName) + strlen (mFvNameGuidString) + 1
5264 );
5265 if (SystemCommand == NULL) {
5266 Status = EFI_ABORTED;
5267 goto Done;
5268 }
5269 sprintf (
5270 SystemCommand,
5271 "BfmLib -r \"%s\" \"%s\" \"%s\" -g %s",
5272 mInputFdName,
5273 FileName,
5274 mOutputFdName,
5275 mFvNameGuidString
5276 );
5277 } else {
5278 SystemCommandFormatString = "BfmLib -r \"%s\" \"%s\" \"%s\"";
5279 SystemCommand = malloc (
5280 strlen (SystemCommandFormatString) + strlen (mInputFdName) + strlen (mOutputFdName) + strlen (FileName) + 1
5281 );
5282 if (SystemCommand == NULL) {
5283 Status = EFI_ABORTED;
5284 goto Done;
5285 }
5286 sprintf (
5287 SystemCommand,
5288 "BfmLib -r \"%s\" \"%s\" \"%s\"",
5289 mInputFdName,
5290 FileName,
5291 mOutputFdName
5292 );
5293 }
5294 } else {
5295 if (mFvNameGuidString != NULL) {
5296 SystemCommandFormatString = "BfmLib -i \"%s\" \"%s\" \"%s\" -g %s";
5297 SystemCommand = malloc (
5298 strlen (SystemCommandFormatString) + strlen (mInputFdName) + strlen (mOutputFdName) + strlen (FileName) + strlen (mFvNameGuidString) + 1
5299 );
5300 if (SystemCommand == NULL) {
5301 Status = EFI_ABORTED;
5302 goto Done;
5303 }
5304 sprintf (
5305 SystemCommand,
5306 "BfmLib -i \"%s\" \"%s\" \"%s\" -g %s",
5307 mInputFdName,
5308 FileName,
5309 mOutputFdName,
5310 mFvNameGuidString
5311 );
5312 } else {
5313 SystemCommandFormatString = "BfmLib -i \"%s\" \"%s\" \"%s\"";
5314 SystemCommand = malloc (
5315 strlen (SystemCommandFormatString) + strlen (mInputFdName) + strlen (mOutputFdName) + strlen (FileName) + 1
5316 );
5317 if (SystemCommand == NULL) {
5318 Status = EFI_ABORTED;
5319 goto Done;
5320 }
5321 sprintf (
5322 SystemCommand,
5323 "BfmLib -i \"%s\" \"%s\" \"%s\"",
5324 mInputFdName,
5325 FileName,
5326 mOutputFdName
5327 );
5328 }
5329 }
5330
5331 if (mFullGuidToolDefinitionDir[0] != 0) {
5332 TempSystemCommand = SystemCommand;
5333 SystemCommand = malloc (
5334 strlen (mFullGuidToolDefinitionDir) + strlen ("\\") + strlen (TempSystemCommand ) + 1
5335 );
5336
5337 if (SystemCommand == NULL) {
5338 free (TempSystemCommand);
5339 goto Done;
5340 }
5341 strcpy (SystemCommand, mFullGuidToolDefinitionDir);
5342 strcat (SystemCommand, OS_SEP_STR);
5343 strcat (SystemCommand, TempSystemCommand);
5344 free (TempSystemCommand);
5345 }
5346
5347 ReturnValue = system (SystemCommand);
5348 free (SystemCommand);
5349 remove (FileName);
5350 if (ReturnValue == -1) {
5351 Status = EFI_ABORTED;
5352 }
5353 Done:
5354 for (Index = 0; SectionName[Index] != NULL; Index++) {
5355 free (SectionName[Index]);
5356 }
5357 if (PreBinary != NULL) {
5358 free (PreBinary);
5359 }
5360 if (Binary) {
5361 free (Binary);
5362 }
5363 return Status;
5364 }
5365
5366 /**
5367 Create the storage and insert it to NvStoreDatabase.
5368
5369 @param InputFdName The pointer to the input fd name.
5370 @param OutputFdName The pointer to the input fd name.
5371 @param VarListEntry The pointer to the variable list.
5372
5373 @return EFI_INVALID_PARAMETER
5374 @return EFI_SUCCESS
5375 **/
5376 EFI_STATUS
5377 InsertBinaryToNvStoreDatabase (
5378 IN CHAR8 *InputFdName,
5379 IN CHAR8 *OutputFdName,
5380 IN LIST_ENTRY *VarListEntry
5381 )
5382 {
5383 UINT8 *Binary;
5384 UINT8 *PreBinary;
5385 UINT8 *NvStoreDatabaseBuffer;
5386 UINT32 PreBinaryLength;
5387 UINT32 Size;
5388 UINT32 NvStoreDatabaseSize;
5389 UINT32 OptimizedSize;
5390 EFI_STATUS Status;
5391 LIST_ENTRY *StorageLink;
5392 FORMSET_STORAGE *Storage;
5393 BOOLEAN SizeOptimizedFlag;
5394 PCD_NV_STORE_DEFAULT_BUFFER_HEADER *NvStoreBufferHeader;
5395 PCD_DEFAULT_DATA *PcdDefaultData;
5396
5397 //
5398 // Workaround for static code checkers.
5399 // Ensures the size of 'IndexStr' can hold all the digits of an unsigned
5400 // 32-bit integer.
5401 //
5402
5403 PreBinaryLength = 0;
5404 Storage = NULL;
5405 StorageLink = NULL;
5406 Binary = NULL;
5407 PreBinary = NULL;
5408 NvStoreDatabaseBuffer = NULL;
5409 PcdDefaultData = NULL;
5410 Size = 0;
5411 NvStoreDatabaseSize = 0;
5412 OptimizedSize = 0;
5413 Status = EFI_SUCCESS;
5414 SizeOptimizedFlag = FALSE;
5415
5416 //
5417 // Allocate the buffer which is the same with the input FD
5418 //
5419
5420 Binary = malloc (SIZE_64K);
5421 if (Binary == NULL) {
5422 printf ("Error. Memory allocation failed.\n");
5423 Status = EFI_ABORTED;
5424 goto Done;
5425 }
5426 NvStoreBufferHeader = (PCD_NV_STORE_DEFAULT_BUFFER_HEADER *) gEfiFdInfo.NvStoreDatabase;
5427 NvStoreDatabaseBuffer = malloc (NvStoreBufferHeader->MaxLength);
5428 if (NvStoreDatabaseBuffer == NULL) {
5429 printf ("Error. Memory allocation failed.\n");
5430 Status = EFI_ABORTED;
5431 goto Done;
5432 }
5433 memcpy(NvStoreDatabaseBuffer, gEfiFdInfo.NvStoreDatabase, NvStoreBufferHeader->MaxLength);
5434 PreBinary = malloc (SIZE_64K);
5435 if (PreBinary == NULL) {
5436 printf ("Error. Memory allocation failed.\n");
5437 Status = EFI_ABORTED;
5438 goto Done;
5439 }
5440
5441 if (gEfiFdInfo.ExistNvStoreDatabase) {
5442 SizeOptimizedFlag = TRUE;
5443 } else {
5444 Status = EFI_ABORTED;
5445 goto Done;
5446 }
5447 //
5448 // Build the binary for BFV
5449 //
5450 StorageLink = GetFirstNode (VarListEntry);
5451 while (!IsNull (VarListEntry, StorageLink)) {
5452 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
5453 if (!Storage->Skip) {
5454 memset(Binary, 0, SIZE_64K);
5455 Size = PutStorageToNvStoreBinary (Storage, Binary, VarListEntry);
5456 assert (Size < SIZE_64K);
5457 //
5458 // Re-calculate the storage section by size optimization
5459 //
5460 if (PreBinaryLength != 0 && SizeOptimizedFlag) {
5461 OptimizedSize = OptimizeStorageDeltaData (
5462 PreBinary,
5463 Binary,
5464 NvStoreDatabaseBuffer + NvStoreDatabaseSize,
5465 Size
5466 );
5467 if (OptimizedSize == 0) {
5468 printf ("Error. Failed to optimize the storage section.\n");
5469 Status = EFI_ABORTED;
5470 goto Done;
5471 }
5472 //Alignment
5473 OptimizedSize = (OptimizedSize + 7) & ~7;
5474 NvStoreDatabaseSize += OptimizedSize;
5475 } else {
5476 //Alignment
5477 Size = (Size + 7) & ~7;
5478 PcdDefaultData = (PCD_DEFAULT_DATA *)Binary;
5479 memcpy(NvStoreDatabaseBuffer + sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER), Binary, Size + PcdDefaultData->HeaderSize + 4 );
5480 PreBinaryLength = Size + PcdDefaultData->HeaderSize + 4;
5481 NvStoreDatabaseSize = sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + PreBinaryLength;
5482 memcpy(PreBinary, Binary, PreBinaryLength);
5483 }
5484 }
5485 StorageLink = GetNextNode (VarListEntry, StorageLink);
5486 }
5487 if (NvStoreBufferHeader->Length != NvStoreDatabaseSize) {
5488 ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)NvStoreDatabaseBuffer)->Length = NvStoreDatabaseSize;
5489 }
5490 memcpy(gEfiFdInfo.NvStoreDatabase, NvStoreDatabaseBuffer, NvStoreDatabaseSize);
5491
5492 Done:
5493 DestroyAllStorage (&mAllVarListEntry);
5494 if (PreBinary != NULL) {
5495 free (PreBinary);
5496 }
5497 if (Binary) {
5498 free (Binary);
5499 }
5500 return Status;
5501 }
5502
5503 extern UINT32 mMaxCount;
5504 extern UINT32 mCount;
5505 extern CHAR8 *mStringBuffer;
5506
5507 /**
5508 Read the HII configure file from all FFS
5509
5510 @retval EFI_SUCCESS It was complete successfully
5511 @return EFI_ABORTED An error occurred
5512 **/
5513 static
5514 EFI_STATUS
5515 ReadCongFile (
5516 VOID
5517 )
5518 {
5519 EFI_STATUS Status;
5520 UINT32 Index;
5521 UINT16 DefaultIndex;
5522 UINT16 PlatformIndex;
5523 UINT16 PreDefaultId;
5524 UINT64 PrePlatformId;
5525 LIST_ENTRY NewStorageListHead;
5526 BOOLEAN BfvOverried;
5527 FORMSET_STORAGE *Storage;
5528 LIST_ENTRY *StorageLink;
5529
5530 Storage = NULL;
5531 Status = EFI_SUCCESS;
5532 BfvOverried = FALSE;
5533 Index = 0;
5534 PreDefaultId = 0xFFFF;
5535 PrePlatformId = 0xFFFFFFFFFFFFFFFF;
5536 //
5537 // Read all Ifr information to Formset list
5538 //
5539 for (Index = 0; (gEfiFdInfo.FfsArray[Index] != NULL) && (gEfiFdInfo.Length[Index] != 0); Index++) {
5540 Status = ReadAllIfrToFromset (
5541 gEfiFdInfo.FfsArray[Index],
5542 gEfiFdInfo.Length[Index]
5543 );
5544 if (EFI_ERROR (Status)) {
5545 return EFI_ABORTED;
5546 }
5547 }
5548 //
5549 // Read defaultId and platformId
5550 //
5551 if (!gEfiFdInfo.ExistNvStoreDatabase) {
5552 Status = ReadDefaultAndPlatformId (&mFormSetListEntry);
5553 if (EFI_ERROR (Status)) {
5554 return EFI_ABORTED;
5555 }
5556 }
5557 //
5558 // If existed the variable data in BFV, abstract them to a variable list.
5559 // If not exsited, just skip it.
5560 //
5561 if (mMultiPlatformParam.MultiPlatformOrNot) {
5562 if (gEfiFdInfo.ExistNvStoreDatabase) {
5563 Status = ReadStorageFromNvStoreDatabase(&mBfvVarListEntry);
5564 } else {
5565 Status = ReadStorageFromBfv (&mBfvVarListEntry);
5566 }
5567 if (!EFI_ERROR (Status)) {
5568 BfvOverried = TRUE;
5569 }
5570 }
5571 //
5572 // If not existed the storage data in BFV, evaluate the
5573 // default value according to the defaultId and platformId
5574 // Or else, skip it.
5575 //
5576 if (!BfvOverried) {
5577 Status = EvaluateTheValueInFormset (FALSE);
5578 if (EFI_ERROR (Status)) {
5579 return EFI_ABORTED;
5580 }
5581 }
5582
5583 //
5584 // Output the question and value information on screen
5585 //
5586 if (mMultiPlatformParam.MultiPlatformOrNot) {
5587 //
5588 // Multi-platform mode support
5589 //
5590 if (gEfiFdInfo.ExistNvStoreDatabase) {
5591 StorageLink = GetFirstNode (&mBfvVarListEntry);
5592 while (!IsNull (&mBfvVarListEntry, StorageLink)) {
5593 Storage = FORMSET_STORAGE_FROM_LINK (StorageLink);
5594 if (PreDefaultId == Storage->DefaultId[0] && PrePlatformId == Storage->PlatformId[0]) {
5595 StorageLink = GetNextNode (&mBfvVarListEntry, StorageLink);
5596 continue;
5597 } else {
5598 PreDefaultId = Storage->DefaultId[0];
5599 PrePlatformId = Storage->PlatformId[0];
5600 }
5601 InitializeListHead(&NewStorageListHead);
5602 //
5603 // Use the varaible stroage list from BFV
5604 //
5605 Status = BuildVariableList(
5606 &NewStorageListHead,
5607 &mBfvVarListEntry,
5608 Storage->DefaultId[0],
5609 Storage->PlatformId[0],
5610 FALSE,
5611 READ
5612 );
5613
5614 if (EFI_ERROR (Status)) {
5615 DestroyAllStorage (&NewStorageListHead);
5616 return EFI_ABORTED;
5617 }
5618 if (IsListEmpty (&NewStorageListHead)) {
5619 continue;
5620 }
5621 Status = PrintInfoInAllFormset (&mFormSetListEntry, &NewStorageListHead);
5622 if (EFI_ERROR (Status)) {
5623 DestroyAllStorage (&NewStorageListHead);
5624 return EFI_ABORTED;
5625 }
5626 DestroyAllStorage (&NewStorageListHead);
5627 StorageLink = GetNextNode (&mBfvVarListEntry, StorageLink);
5628 }
5629 } else {
5630 for (DefaultIndex = 0; DefaultIndex < mMultiPlatformParam.DefaultIdNum; DefaultIndex++) {
5631 for (PlatformIndex = 0; PlatformIndex < mMultiPlatformParam.PlatformIdNum; PlatformIndex++) {
5632 InitializeListHead(&NewStorageListHead);
5633 if (BfvOverried) {
5634 //
5635 // Use the varaible stroage list from BFV
5636 //
5637 Status = BuildVariableList(
5638 &NewStorageListHead,
5639 &mBfvVarListEntry,
5640 mMultiPlatformParam.DefaultId[DefaultIndex],
5641 mMultiPlatformParam.PlatformId[PlatformIndex],
5642 FALSE,
5643 READ
5644 );
5645 } else {
5646 //
5647 // Use the varaible storage list from IFR
5648 //
5649 Status = BuildVariableList(
5650 &NewStorageListHead,
5651 &mAllVarListEntry,
5652 mMultiPlatformParam.DefaultId[DefaultIndex],
5653 mMultiPlatformParam.PlatformId[PlatformIndex],
5654 FALSE,
5655 READ
5656 );
5657 }
5658 if (EFI_ERROR (Status)) {
5659 DestroyAllStorage (&NewStorageListHead);
5660 return EFI_ABORTED;
5661 }
5662 if (IsListEmpty (&NewStorageListHead)) {
5663 continue;
5664 }
5665 Status = PrintInfoInAllFormset (&mFormSetListEntry, &NewStorageListHead);
5666 if (EFI_ERROR (Status)) {
5667 DestroyAllStorage (&NewStorageListHead);
5668 return EFI_ABORTED;
5669 }
5670 DestroyAllStorage (&NewStorageListHead);
5671 }
5672 }
5673 }
5674 } else {
5675 Status = PrintInfoInAllFormset (&mFormSetListEntry, &mAllVarListEntry);
5676 if (EFI_ERROR (Status)) {
5677 return EFI_ABORTED;
5678 }
5679 }
5680
5681 return Status;
5682 }
5683
5684 /**
5685 Update the HII setup value.
5686
5687 Read the Config information from config file, and then compare it with the current FFS.
5688 Record the different value to EFI variable.
5689
5690 @param Fv the Pointer to the FFS
5691 @param Length the length of FFS
5692
5693 @retval EFI_SUCCESS It was complete successfully
5694 @return EFI_ABORTED An error occurred
5695 **/
5696 static
5697 EFI_STATUS
5698 UpdateCongFile (
5699 VOID
5700 )
5701 {
5702 EFI_STATUS Status;
5703 UINT32 Index;
5704 BOOLEAN BfvOverried;
5705
5706 Status = EFI_SUCCESS;
5707 BfvOverried = FALSE;
5708 Index = 0;
5709 //
5710 // Read all Ifr information to Formset list
5711 //
5712 for (Index = 0; (gEfiFdInfo.FfsArray[Index] != NULL) && (gEfiFdInfo.Length[Index] != 0); Index++) {
5713 Status = ReadAllIfrToFromset (
5714 gEfiFdInfo.FfsArray[Index],
5715 gEfiFdInfo.Length[Index]
5716 );
5717 if (EFI_ERROR (Status)) {
5718 return EFI_ABORTED;
5719 }
5720 }
5721 //
5722 // Read defaultId and platformId
5723 //
5724 if (!gEfiFdInfo.ExistNvStoreDatabase) {
5725 Status = ReadDefaultAndPlatformId (&mFormSetListEntry);
5726 if (EFI_ERROR (Status)) {
5727 return EFI_ABORTED;
5728 }
5729 }
5730 //
5731 // If existed the variable data in BFV, abstract them to a variable list.
5732 // If not exsited, just skip it.
5733 //
5734 if (mMultiPlatformParam.MultiPlatformOrNot) {
5735 if (gEfiFdInfo.ExistNvStoreDatabase) {
5736 Status = ReadStorageFromNvStoreDatabase (&mBfvVarListEntry);
5737 } else {
5738 Status = ReadStorageFromBfv (&mBfvVarListEntry);
5739 }
5740 if (!EFI_ERROR (Status)) {
5741 BfvOverried = TRUE;
5742 }
5743 }
5744 if (mMultiPlatformParam.MultiPlatformOrNot && BfvOverried) {
5745 if (mUqiList == NULL) {
5746 return EFI_SUCCESS;
5747 }
5748 Status = CheckValueUpdateList ();
5749 if (EFI_ERROR (Status)) {
5750 return EFI_ABORTED;
5751 }
5752 } else {
5753 //
5754 // Evaluate the default value according to the defaultId and platformId
5755 //
5756 if (mUqiList == NULL) {
5757 Status = EvaluateTheValueInFormset (FALSE);
5758 } else {
5759 Status = EvaluateTheValueInFormset (TRUE);
5760 }
5761 if (EFI_ERROR (Status)) {
5762 return EFI_ABORTED;
5763 }
5764 }
5765 //
5766 // print error information in UQI list
5767 //
5768 if (PrintErrorInfo (mUqiList)) {
5769 return EFI_ABORTED;
5770 }
5771 //
5772 // Output the variable information to BFV in multi-platform mode
5773 // Or write it to the Nvstrage in general mode
5774 //
5775 if (mMultiPlatformParam.MultiPlatformOrNot) {
5776 if (ExistEfiVarOrNot (&mAllVarListEntry) && Operations == UPDATE) {
5777 printf ("Error. Please use --remove or --ignore to update the variable storage for an FD with variables in its NvStorage.\n");
5778 return EFI_ABORTED;
5779 }
5780 } else {
5781 //
5782 // Sync the data from List data to efi variable.
5783 //
5784 Status = EfiVarAndListExchange (FALSE, &mAllVarListEntry);
5785 if (Status == EFI_OUT_OF_RESOURCES) {
5786 printf ("Error. There is no available space in efi variable. \n");
5787 return EFI_ABORTED;
5788 }
5789 if (Status == EFI_INVALID_PARAMETER) {
5790 return EFI_ABORTED;
5791 }
5792 }
5793
5794 PrintUpdateListInfo (mUqiList);
5795
5796 return Status;
5797 }
5798
5799 /**
5800 Quick Update the HII setup value.
5801
5802 Read the Config information from command line directly, and then compare it with the current FFS.
5803 Record the different value to EFI variable.
5804
5805 @retval EFI_SUCCESS It was complete successfully
5806 @return EFI_ABORTED An error occurred
5807 **/
5808
5809 EFI_STATUS
5810 QuickUpdateCongFile (
5811 VOID
5812 )
5813 {
5814 EFI_STATUS Status;
5815 UINT32 Index;
5816
5817 Status = EFI_SUCCESS;
5818 Index = 0;
5819
5820 if (mMultiPlatformParam.MultiPlatformOrNot) {
5821 printf ("Error. The quick update operation is not supported in multi-platform mode.\n");
5822 return EFI_ABORTED;
5823 }
5824 //
5825 // Check whether the FD has included the storage FFS
5826 //
5827 if (mMultiPlatformParam.ExistStorageFfsInBfv) {
5828 printf ("Error. Variable storage exists in BFV of Fd. This is generated in multi-platform mode.\n");
5829 printf ("Error. The quick update operation is not supported in multi-platform mode.\n");
5830 return EFI_ABORTED;
5831 }
5832 //
5833 // Read all Ifr information to Formset list
5834 //
5835 for (Index = 0; (gEfiFdInfo.FfsArray[Index] != NULL) && (gEfiFdInfo.Length[Index] != 0); Index++) {
5836 Status = ReadAllIfrToFromset (
5837 gEfiFdInfo.FfsArray[Index],
5838 gEfiFdInfo.Length[Index]
5839 );
5840 if (EFI_ERROR (Status)) {
5841 return EFI_ABORTED;
5842 }
5843 }
5844 //
5845 // Evaluate the default value according to the defaultId and platformId
5846 //
5847 Status = EvaluateTheValueInFormset (TRUE);
5848 if (EFI_ERROR (Status)) {
5849 return EFI_ABORTED;
5850 }
5851 //
5852 // print error information in UQI list
5853 //
5854 if (PrintErrorInfo (mUqiList)) {
5855 return EFI_ABORTED;
5856 }
5857 //
5858 // Sync the data from mAllVarListEntry data to efi variable.
5859 //
5860 Status = EfiVarAndListExchange (FALSE, &mAllVarListEntry);
5861 if (Status == EFI_OUT_OF_RESOURCES) {
5862 printf ("Error. There is no available space in Nvstorage. \n");
5863 return EFI_ABORTED;
5864 }
5865 if (Status == EFI_INVALID_PARAMETER) {
5866 return EFI_ABORTED;
5867 }
5868
5869 PrintUpdateListInfo (mUqiList);
5870
5871 return Status;
5872 }
5873
5874 /**
5875 Check the HII setup value.
5876
5877 Read the Config information from config file, and then compare it with the current FFS.
5878 Print the different values on screen.
5879
5880 @retval EFI_SUCCESS It was complete successfully
5881 @return EFI_ABORTED An error occurred
5882 **/
5883 static
5884 EFI_STATUS
5885 CheckCongFile (
5886 VOID
5887 )
5888 {
5889 EFI_STATUS Status;
5890 UINT32 Index;
5891 UINT16 DefaultIndex;
5892 UINT16 PlatformIndex;
5893 UINT16 DefaultId;
5894 UINT64 PlatformId;
5895
5896 Status = EFI_SUCCESS;
5897 Index = 0;
5898 DefaultIndex = 0;
5899 PlatformIndex = 0;
5900 DefaultId = 0;
5901 PlatformId = 0;
5902 //
5903 // Read all Ifr information to Formset list
5904 //
5905 for (Index = 0; (gEfiFdInfo.FfsArray[Index] != NULL) && (gEfiFdInfo.Length[Index] != 0); Index++) {
5906 Status = ReadAllIfrToFromset (
5907 gEfiFdInfo.FfsArray[Index],
5908 gEfiFdInfo.Length[Index]
5909 );
5910 if (EFI_ERROR (Status)) {
5911 return EFI_ABORTED;
5912 }
5913 }
5914 //
5915 // Read defaultId and platformId
5916 //
5917 Status = ReadDefaultAndPlatformId (&mFormSetListEntry);
5918 if (EFI_ERROR (Status)) {
5919 return EFI_ABORTED;
5920 }
5921 //
5922 // Read the config data from BFV in multi-platform mode
5923 //
5924 if (mMultiPlatformParam.MultiPlatformOrNot) {
5925 Status = ReadStorageFromBfv (&mAllVarListEntry);
5926 if (EFI_ERROR (Status)) {
5927 printf ("Error. No storage variable data exists in BFV.\n");
5928 return EFI_ABORTED;
5929 }
5930 }
5931
5932 if (mMultiPlatformParam.MultiPlatformOrNot) {
5933 ScanUqiFullList (mUqiList);
5934
5935 //
5936 // Multi-platform mode support
5937 //
5938 for (DefaultIndex = 0; DefaultIndex < mMultiPlatformParam.DefaultIdNum; DefaultIndex++) {
5939 for (PlatformIndex = 0; PlatformIndex < mMultiPlatformParam.PlatformIdNum; PlatformIndex++) {
5940 DefaultId = mMultiPlatformParam.DefaultId[DefaultIndex];
5941 PlatformId = mMultiPlatformParam.PlatformId[PlatformIndex];
5942 //
5943 //Only parse one time, if a group of defaultId and platformId which have the same variable
5944 // Take the first one as a key Id of a group
5945 //
5946 if (NoTheKeyIdOfGroup (DefaultId, PlatformId)) {
5947 continue;
5948 }
5949
5950 InitializeListHead(&mVarListEntry);
5951 Status = BuildVariableList(
5952 &mVarListEntry,
5953 &mAllVarListEntry,
5954 DefaultId,
5955 PlatformId,
5956 FALSE,
5957 VERIFY
5958 );
5959 if (EFI_ERROR (Status)) {
5960 return EFI_ABORTED;
5961 }
5962 if (IsListEmpty (&mVarListEntry)) {
5963 continue;
5964 }
5965 SetUqiParametersMultiMode (mUqiList, DefaultId, PlatformId);
5966 DestroyAllStorage (&mVarListEntry);
5967 }
5968 }
5969 } else {
5970 //
5971 // General mode
5972 //
5973 Status = ExtractDefault (
5974 NULL,
5975 NULL,
5976 0,
5977 0,
5978 SystemLevel
5979 );
5980 if (EFI_ERROR (Status)) {
5981 return EFI_ABORTED;
5982 }
5983 //
5984 // If existed the variable in NvStorage, copy them to mVarListEntry.
5985 // Synchronize the default value from the EFI variable zone to variable list
5986 //
5987 Status = EfiVarAndListExchange (TRUE, &mVarListEntry);
5988 if (Status == EFI_INVALID_PARAMETER) {
5989 Status = EFI_ABORTED;
5990 return Status;
5991 }
5992 //
5993 // Update the value from script file
5994 //
5995 Status = SetUqiParameters (mUqiList,0, 0);
5996 if (EFI_ERROR (Status)) {
5997 return EFI_ABORTED;
5998 }
5999 //
6000 // Copy Stroage from mVarListEntry to mAllVarListEntry
6001 //
6002 Status = BuildVariableList (&mAllVarListEntry, &mVarListEntry, 0, 0, TRUE, VERIFY);
6003 if (EFI_ERROR (Status)) {
6004 return EFI_ABORTED;
6005 }
6006 }
6007 PrintVerifiedListInfo (mUqiList);
6008 return Status;
6009 }
6010
6011 /**
6012 Search the config file from the path list.
6013
6014 Split the path from env PATH, and then search the cofig
6015 file from these paths. The priority is from left to
6016 right of PATH string. When met the first Config file, it
6017 will break and return the pointer to the full file name.
6018
6019 @param PathList the pointer to the path list.
6020 @param FileName the pointer to the file name.
6021
6022 @retval The pointer to the file name.
6023 @return NULL An error occurred.
6024 **/
6025 CHAR8 *
6026 SearchConfigFromPathList (
6027 IN CHAR8 *PathList,
6028 IN CHAR8 *FileName
6029 )
6030 {
6031 CHAR8 *CurDir;
6032 CHAR8 *FileNamePath;
6033
6034 CurDir = NULL;
6035 FileNamePath = NULL;
6036 #ifndef __GNUC__
6037 CurDir = strtok (PathList,";");
6038 #else
6039 CurDir = strtok (PathList,":");
6040 #endif
6041 while (CurDir != NULL) {
6042 FileNamePath = (char *)calloc(
6043 strlen (CurDir) + strlen (OS_SEP_STR) +strlen (FileName) + 1,
6044 sizeof(char)
6045 );
6046 if (FileNamePath == NULL) {
6047 return NULL;
6048 }
6049 sprintf(FileNamePath, "%s%c%s", CurDir, OS_SEP, FileName);
6050 if (access (FileNamePath, 0) != -1) {
6051 return FileNamePath;
6052 }
6053 #ifndef __GNUC__
6054 CurDir = strtok(NULL, ";");
6055 #else
6056 CurDir = strtok(NULL, ":");
6057 #endif
6058 free (FileNamePath);
6059 FileNamePath = NULL;
6060 }
6061 return NULL;
6062 }
6063
6064 /**
6065 FCE application entry point
6066
6067 @param argc The number of input parameters.
6068 @param *argv[] The array pointer to the parameters.
6069
6070 @retval 0 The application exited normally.
6071 @retval 1 An error occurred.
6072 @retval 2 An error about check occurred.
6073
6074 **/
6075 int
6076 main (
6077 int argc,
6078 char *argv[]
6079 )
6080 {
6081 EFI_STATUS Status;
6082 FILE *OutputFd;
6083 FILE *ScriptFile;
6084 UINTN BytesWrite;
6085 UINTN Index;
6086 CHAR8 *TemDir;
6087 BOOLEAN IsFileExist;
6088 CHAR8 FullGuidToolDefinition[_MAX_PATH];
6089 CHAR8 *PathList;
6090 UINTN EnvLen;
6091 CHAR8 *NewPathList;
6092 UINTN FileNameIndex;
6093 CHAR8 *InFilePath;
6094 BOOLEAN UqiIsSet;
6095
6096 Status = EFI_SUCCESS;
6097 OutputFd = NULL;
6098 ScriptFile = NULL;
6099 Operations = NONE;
6100 BytesWrite = 0;
6101 Index = 0;
6102 TemDir = NULL;
6103 mFormSetOrderRead = 0;
6104 mFormSetOrderParse = 0;
6105 IsFileExist = TRUE;
6106 PathList = NULL;
6107 NewPathList = NULL;
6108 EnvLen = 0;
6109 UqiIsSet = FALSE;
6110
6111 TemDir = getcwd (NULL, _MAX_PATH);
6112 if (strlen (TemDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
6113 printf ("The directory is too long \n");
6114 return FAIL;
6115 }
6116 strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1);
6117 strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1);
6118 memset (&mMultiPlatformParam, 0, sizeof (MULTI_PLATFORM_PARAMETERS));
6119
6120 SetUtilityName (UTILITY_NAME);
6121 //
6122 // Workaroud: the first call to this function
6123 // returns a file name ends with dot
6124 //
6125 #ifndef __GNUC__
6126 tmpnam (NULL);
6127 #else
6128 CHAR8 tmp[] = "/tmp/fileXXXXXX";
6129 UINTN Fdtmp;
6130 Fdtmp = mkstemp(tmp);
6131 close(Fdtmp);
6132 #endif
6133 //
6134 // Save, and then skip filename arg
6135 //
6136 mUtilityFilename = argv[0];
6137 argc--;
6138 argv++;
6139 //
6140 // Get the same path with the application itself
6141 //
6142 if (strlen (mUtilityFilename) > _MAX_PATH - 1) {
6143 Error (NULL, 0, 2000, "Parameter: The input file name is too long", NULL);
6144 return FAIL;
6145 }
6146 strncpy (FullGuidToolDefinition, mUtilityFilename, _MAX_PATH - 1);
6147 FullGuidToolDefinition[_MAX_PATH - 1] = 0;
6148 FileNameIndex = strlen (FullGuidToolDefinition);
6149 while (FileNameIndex != 0) {
6150 FileNameIndex --;
6151 if (FullGuidToolDefinition[FileNameIndex] == OS_SEP) {
6152 FullGuidToolDefinition[FileNameIndex] = 0;
6153 strcpy (mFullGuidToolDefinitionDir, FullGuidToolDefinition);
6154 break;
6155 }
6156 }
6157 //
6158 // Build the path list for Config file scan. The priority is below.
6159 // 1. Scan the current path
6160 // 2. Scan the same path with the application itself
6161 // 3. Scan the current %PATH% of OS environment
6162 // 4. Use the build-in default configuration
6163 //
6164 PathList = getenv("PATH");
6165 if (PathList == NULL) {
6166 Error (NULL, 0, 1001, "Option: Environment variable 'PATH' does not exist", NULL);
6167 return FAIL;
6168 }
6169 EnvLen = strlen(PathList);
6170 NewPathList = (char *)calloc(
6171 strlen (".")
6172 + strlen (";")
6173 + strlen (mFullGuidToolDefinitionDir)
6174 + strlen (";")
6175 + EnvLen
6176 + 1,
6177 sizeof(char)
6178 );
6179 if (NewPathList == NULL) {
6180 Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
6181 PathList = NULL;
6182 free (PathList);
6183 return -1;
6184 }
6185 #ifndef __GNUC__
6186 sprintf (NewPathList, "%s;%s;%s", ".", mFullGuidToolDefinitionDir, PathList);
6187 #else
6188 sprintf (NewPathList, "%s:%s:%s", ".", mFullGuidToolDefinitionDir, PathList);
6189 #endif
6190
6191 PathList = NULL;
6192 free (PathList);
6193
6194 //
6195 // Load Guid Tools definition
6196 //
6197 InFilePath = SearchConfigFromPathList(NewPathList, mGuidToolDefinition);
6198 free (NewPathList);
6199 if (InFilePath != NULL) {
6200 printf ("\nThe Guid Tool Definition comes from the '%s'. \n", InFilePath);
6201 mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (InFilePath);
6202 free (InFilePath);
6203 } else {
6204 //
6205 // Use the pre-defined standard guided tools.
6206 //
6207 printf ("\nThe Guid Tool Definition comes from the build-in default configuration. \n");
6208 mParsedGuidedSectionTools = PreDefinedGuidedTools ();
6209 }
6210 //
6211 // Parse the command line
6212 //
6213 strcpy (mSetupTxtName, "NoSetupFile");
6214 Status = ParseCommmadLine (argc,argv);
6215 if (EFI_ERROR (Status)) {
6216 return FAIL;
6217 }
6218 //
6219 // Print utility header
6220 //
6221 printf ("\nIntel(R) Firmware Configuration Editor. (Intel(R) %s) Version %d.%d. %s.\n\n",
6222 UTILITY_NAME,
6223 UTILITY_MAJOR_VERSION,
6224 UTILITY_MINOR_VERSION,
6225 __BUILD_VERSION
6226 );
6227 //
6228 // Check the revision of BfmLib
6229 //
6230 Status = CheckBfmLibRevision ();
6231 if (EFI_ERROR (Status)) {
6232 printf ("Please use the correct revision of BfmLib %s. \n", __BUILD_VERSION);
6233 return FAIL;
6234 }
6235 if (strcmp (mSetupTxtName, "NoSetupFile")) {
6236 ScriptFile = fopen (mSetupTxtName, "r");
6237 if (ScriptFile == NULL) {
6238 printf ("Error. Cannot open the script file.\n");
6239 return FAIL;
6240 }
6241 Status = PickUpUqiFromScript (ScriptFile);
6242 if (EFI_ERROR (Status)) {
6243 fclose (ScriptFile);
6244 IsFileExist = FALSE;
6245 goto Done;
6246 }
6247 fclose (ScriptFile);
6248 }
6249 if (!mMultiPlatformParam.MultiPlatformOrNot
6250 && (Operations == UPDATE_REMOVE || Operations == UPDATE_IGNORE)
6251 ) {
6252 printf ("Error. --remove and --ignore cannot be used in normal mode.\n");
6253 Status = FAIL;
6254 goto Done;
6255 }
6256
6257 if (access (TemDir, 0) != -1) {
6258 LibRmDir (TemDir);
6259 }
6260
6261 //
6262 // Initialize the variables
6263 //
6264 Status = PickUpFfsFromFd ();
6265 if (EFI_ERROR (Status)) {
6266 printf ("Error. Invalid FD file.\n");
6267 IsFileExist = FALSE;
6268 Status = FAIL;
6269 goto Done;
6270 }
6271 if (gEfiFdInfo.FfsArray[0] == NULL) {
6272 printf ("Error. Cannot find any HII offset in current FD files, please check the BaseTools.\n");
6273 Status = FAIL;
6274 goto Done;
6275 }
6276 //
6277 //Config the global variables
6278 //
6279 if (mMultiPlatformParam.Uqi.Data != NULL) {
6280 UqiIsSet = TRUE;
6281 }
6282 Status = GetEfiVariablesAddr (UqiIsSet);
6283 if (EFI_ERROR (Status)) {
6284 printf ("Error. Cannot locate the EFI variable zone in FD.\n");
6285 Status = FAIL;
6286 goto Done;
6287 }
6288 if (gEfiFdInfo.ExistNvStoreDatabase && !mMultiPlatformParam.MultiPlatformOrNot) {
6289 mMultiPlatformParam.MultiPlatformOrNot = TRUE;
6290 }
6291 //
6292 // Initialize the FormSet and VarList List
6293 //
6294 InitializeListHead (&mFormSetListEntry);
6295 InitializeListHead (&mVarListEntry);
6296 InitializeListHead (&mBfvVarListEntry);
6297 InitializeListHead (&mAllVarListEntry);
6298
6299 mStringBuffer = malloc (mMaxCount);
6300 if (mStringBuffer == NULL) {
6301 printf ("Fali to allocate memory!\n");
6302 Status = FAIL;
6303 goto Done;
6304 }
6305
6306 //
6307 // Decide how to deal with the Fd
6308 //
6309 switch (Operations) {
6310
6311 case READ:
6312 printf ("\nStart the Read Mode:\n");
6313 Status = ReadCongFile ();
6314 if (EFI_ERROR (Status)) {
6315 Status = FAIL;
6316 }
6317 break;
6318
6319 case UPDATE:
6320 case UPDATE_REMOVE:
6321 case UPDATE_IGNORE:
6322 printf ("\nStart the Update Mode:\n");
6323 Status = UpdateCongFile ();
6324 if (EFI_ERROR (Status)) {
6325 Status = FAIL;
6326 }
6327 break;
6328
6329 case VERIFY:
6330 printf ("\nStart the Verify Mode:\n");
6331 Status = CheckCongFile ();
6332 if (EFI_ERROR (Status)) {
6333 Status = VR_FAIL;
6334 }
6335 break;
6336
6337 case UPDATEQ:
6338 printf ("\nStart the Update Quick Mode:\n");
6339 Status = QuickUpdateCongFile ();
6340 if (EFI_ERROR (Status)) {
6341 Status = FAIL;
6342 }
6343 break;
6344
6345 default:
6346 break;
6347 }
6348
6349 if (mCount > 0) {
6350 mStringBuffer[mCount] = '\0';
6351 fwrite (mStringBuffer, sizeof (CHAR8), mCount, stdout);
6352 }
6353 free (mStringBuffer);
6354
6355 if (Status != SUCCESS) {
6356 goto Done;
6357 }
6358 //
6359 // If multi-platform mode, insert the variables to BFV
6360 //
6361 if (mMultiPlatformParam.MultiPlatformOrNot
6362 && (IsListEmpty (&mAllVarListEntry) == FALSE)
6363 &&((Operations == UPDATE) || (Operations == UPDATE_REMOVE) || (Operations == UPDATE_IGNORE) || (Operations == UPDATEQ))
6364 ) {
6365 IsFileExist = FALSE;
6366 if (gEfiFdInfo.ExistNvStoreDatabase) {
6367 Status = InsertBinaryToNvStoreDatabase (mInputFdName, mOutputFdName, &mAllVarListEntry);
6368 } else {
6369 Status = InsertBinaryToBfv (mInputFdName, mOutputFdName, &mAllVarListEntry);
6370 }
6371 if (EFI_ERROR (Status)) {
6372 goto Done;
6373 }
6374 //
6375 // Remove the variables in NvStorage in multi-platform mode by user specified requirement
6376 //
6377 if (Operations == UPDATE_REMOVE) {
6378 if (gEfiFdInfo.Fd != NULL) {
6379 free (gEfiFdInfo.Fd);
6380 }
6381 gEfiFdInfo.Fd = ReadFileToMemory (mOutputFdName, &gEfiFdInfo.FdSize);
6382 if (gEfiFdInfo.Fd == NULL) {
6383 Status = EFI_ABORTED;
6384 } else {
6385 Status = RemoveEfiVar (&mAllVarListEntry);
6386 }
6387 if (EFI_ERROR (Status)) {
6388 printf ("Error. Failed to remove the variable from NVRAM.\n");
6389 Status = FAIL;
6390 goto Done;
6391 }
6392 }
6393 }
6394
6395 if (
6396 (!mMultiPlatformParam.MultiPlatformOrNot &&((Operations == UPDATE) || (Operations == UPDATEQ)))
6397 || (mMultiPlatformParam.MultiPlatformOrNot && (Operations == UPDATE_REMOVE || ((Operations == UPDATE) && IsListEmpty (&mAllVarListEntry))))
6398 ) {
6399 OutputFd = fopen (mOutputFdName, "wb+");
6400 if (OutputFd == NULL) {
6401 printf ("Error. Failed to create the output FD file.\n");
6402 Status = FAIL;
6403 goto Done;
6404 }
6405 fseek (OutputFd, 0, SEEK_SET);
6406 BytesWrite = fwrite (gEfiFdInfo.Fd, sizeof (CHAR8), gEfiFdInfo.FdSize, OutputFd);
6407 fclose (OutputFd);
6408 if (BytesWrite != gEfiFdInfo.FdSize) {
6409 printf ("Error. Failed to create the FD image. \n");
6410 Status = FAIL;
6411 goto Done;
6412 }
6413 }
6414 if ((Operations == UPDATE) || (Operations == UPDATE_REMOVE) || (Operations == UPDATE_IGNORE) || (Operations == UPDATEQ)) {
6415 printf ("\nCongratulations. The output Fd file '%s' has been completed successfully.\n", mOutputFdName);
6416 }
6417 Done:
6418 //
6419 // Delete the temporary directory and files
6420 //
6421 if (IsFileExist) {
6422 LibRmDir (TemDir);
6423 }
6424 //
6425 // Clean up
6426 //
6427 if (gEfiFdInfo.Fd != NULL) {
6428 free (gEfiFdInfo.Fd);
6429 }
6430
6431 if (mMultiPlatformParam.Uqi.Value != NULL) {
6432 free (mMultiPlatformParam.Uqi.Value);
6433 }
6434 if (mMultiPlatformParam.Uqi.Data != NULL) {
6435 free (mMultiPlatformParam.Uqi.Data);
6436 }
6437 while (gEfiFdInfo.FfsArray[Index] != NULL) {
6438 free (gEfiFdInfo.FfsArray[Index++]);
6439 }
6440
6441 DestroyAllFormSet (&mFormSetListEntry);
6442 DestroyAllStorage (&mVarListEntry);
6443 DestroyAllStorage (&mBfvVarListEntry);
6444 DestroyAllStorage (&mAllVarListEntry);
6445 FreeUnidirectionList (mUqiList);
6446
6447 return Status;
6448 }
6449