/** @file FCE is a tool which enables developers to retrieve and change HII configuration ("Setup") data in Firmware Device files (".fd" files). Copyright (c) 2011-2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Fce.h" #ifndef __GNUC__ #define COPY_STR "copy \"%s\" \"%s\" > NUL" #define RMDIR_STR "rmdir /S /Q \"%s\" > NUL" #define DEL_STR "del \"%s\" > NUL" #else #define COPY_STR "cp \"%s\" \"%s\" > /dev/null" #define RMDIR_STR "rm -r \"%s\" > /dev/null" #define DEL_STR "rm \"%s\" > /dev/null" #endif // // Utility global variables // OPERATION_TYPE Operations; CHAR8 mInputFdName[MAX_FILENAME_LEN]; CHAR8 mOutputFdName[MAX_FILENAME_LEN]; CHAR8 mOutTxtName[MAX_FILENAME_LEN]; CHAR8 mSetupTxtName[MAX_FILENAME_LEN]; CHAR8* mUtilityFilename = NULL; UINT32 mEfiVariableAddr = 0; UQI_PARAM_LIST *mUqiList = NULL; UQI_PARAM_LIST *mLastUqiList = NULL; LIST_ENTRY mVarListEntry; LIST_ENTRY mBfvVarListEntry; LIST_ENTRY mAllVarListEntry; LIST_ENTRY mFormSetListEntry; // // Store GUIDed Section guid->tool mapping // EFI_HANDLE mParsedGuidedSectionTools = NULL; CHAR8* mGuidToolDefinition = "GuidToolDefinitionConf.ini"; // //gFfsArray is used to store all the FFS informations of Fd // G_EFI_FD_INFO gEfiFdInfo; // //mMultiPlatformParam is used to store the structures about multi-platform support // MULTI_PLATFORM_PARAMETERS mMultiPlatformParam; UINT32 mFormSetOrderRead; UINT32 mFormSetOrderParse; CHAR8 mFullGuidToolDefinitionDir[_MAX_PATH]; CHAR8 *mFvNameGuidString = NULL; /** Check the revision of BfmLib. If not matched, return an error. @retval EFI_SUCCESS If revision matched, return EFI_SUCCESS. @retval EFI_UNSUPPORTED Other cases. **/ static EFI_STATUS CheckBfmLibRevision ( VOID ) { CHAR8 *SystemCommandFormatString; CHAR8 *SystemCommand; CHAR8 *TempSystemCommand; CHAR8 *Revision; FILE *FileHandle; CHAR8 RevisionStr[_MAX_BUILD_VERSION]; UINT32 Len; SystemCommandFormatString = NULL; SystemCommand = NULL; TempSystemCommand = NULL; Revision = "Revision.txt"; memset (RevisionStr, 0, _MAX_BUILD_VERSION); // // Construction 'system' command string // SystemCommandFormatString = "BfmLib -v > %s"; SystemCommand = malloc ( strlen (SystemCommandFormatString) + strlen (Revision) + 1 ); if (SystemCommand == NULL) { return EFI_UNSUPPORTED; } sprintf ( SystemCommand, "BfmLib -v > %s", Revision ); if (mFullGuidToolDefinitionDir[0] != 0) { TempSystemCommand = SystemCommand; SystemCommand = malloc ( strlen (mFullGuidToolDefinitionDir) + strlen (OS_SEP_STR) + strlen (SystemCommandFormatString) + strlen (Revision) + 1 ); if (SystemCommand == NULL) { free (TempSystemCommand); return EFI_UNSUPPORTED; } strcpy (SystemCommand, mFullGuidToolDefinitionDir); strcat (SystemCommand, OS_SEP_STR); strcat (SystemCommand, TempSystemCommand); free (TempSystemCommand); } system (SystemCommand); free (SystemCommand); FileHandle = fopen (Revision, "r"); if (FileHandle == NULL) { printf ("Error. Read the revision file of BfmLib failed.\n"); return EFI_ABORTED; } fgets(RevisionStr, _MAX_BUILD_VERSION, FileHandle); Len = strlen(RevisionStr); if (RevisionStr[Len - 1] == '\n') { RevisionStr[Len - 1] = 0; } fclose (FileHandle); remove (Revision); if (strlen (RevisionStr) > _MAX_BUILD_VERSION - 1) { printf ("The revision string is too long"); return EFI_UNSUPPORTED; } if (strcmp (RevisionStr, __BUILD_VERSION) == 0) { return EFI_SUCCESS; } return EFI_UNSUPPORTED; } /** Transfer the Ascii string to the Dec Number @param InStr The Ascii string. @retval DecNum Return the Dec number. **/ static UINT64 StrToDec ( IN CHAR8 *InStr ) { UINT8 Index; UINTN DecNum; UINTN Temp; Index = 0; DecNum = 0; Temp = 0; if (InStr == NULL) { return (UINT64)-1; } while (Index < strlen (InStr)) { if ((*(InStr + Index) >= '0') && (*(InStr + Index) <= '9')) { Temp = *(InStr + Index) - '0'; } else if ((*(InStr + Index) >= 'a') && (*(InStr + Index) <= 'f')) { Temp = *(InStr + Index) - 'a' + 10; } else if ((*(InStr + Index) >= 'A') && (*(InStr + Index) <= 'F')) { Temp = *(InStr + Index) - 'A' + 10; } DecNum = DecNum + Temp * (UINTN) pow (16, strlen (InStr) - Index - 1); Index++; } return DecNum; } /** Check whether there are some errors in uqi parameters of One_of @param Question The pointer to the question Node. @param UqiValue The value of One_of. @retval TRUE If existed error, return TRUE; @return FALSE Otherwise, return FALSE; **/ static BOOLEAN CheckOneOfParamError ( IN CONST FORM_BROWSER_STATEMENT *Question, IN UINT64 UqiValue ) { LIST_ENTRY *Link; QUESTION_OPTION *Option; UINT64 Value; Link = NULL; Option = NULL; Value = 0; Link = GetFirstNode (&Question->OptionListHead); while (!IsNull (&Question->OptionListHead, Link)) { Option = QUESTION_OPTION_FROM_LINK (Link); Value = 0; CopyMem (&Value, &Option->Value.Value.u64, Question->StorageWidth); if (Value == UqiValue) { return FALSE; } Link = GetNextNode (&Question->OptionListHead, Link); } return TRUE; } /** Check whether there are some errors in uqi parameters of Orderlist @param HiiObjList The pointer to the Hii Object Node. @param UqiValue The pointer to the Uqi parameter. @retval TRUE If existed error, return TRUE; @return FALSE Otherwise, return FALSE; **/ static BOOLEAN CheckOrderParamError ( IN CONST FORM_BROWSER_STATEMENT *Question, IN CHAR8 *UqiValue ) { UINT8 MaxNum; MaxNum = UqiValue[0]; if (MaxNum != (UINT8)(Question->MaxContainers)) { return TRUE; } return FALSE; } /** Writes a Unicode string @param Package A pointer to the Unicode string. @return NULL **/ static VOID WriteUnicodeStr ( IN CHAR16 *pcString ) { UINTN Index; if (pcString == NULL) { return; } for (Index = 0; pcString[Index] != 0; Index++) { printf("%c", pcString[Index] & 0x00FF); } } /** Parse and set the quick configure information by the command line. Read the UQI Config information from command line directly, and then compare it with the value in VarList. Update the Update flag in Varlist. @param CurUqiList The pointer to the current uqi @param DefaultId The default Id. @param PlatformId The platform Id. @param CurQuestion The pointer to the matched question @retval EFI_SUCCESS It was complete successfully @retval EFI_UNSUPPORTED Update a read-only value @return EFI_ABORTED An error occurred **/ static EFI_STATUS SetUqiParametersWithQuestion ( IN UQI_PARAM_LIST *CurUqiList, IN UINT16 DefaultId, IN UINT64 PlatformId, IN FORM_BROWSER_STATEMENT *CurQuestion ) { FORMSET_STORAGE *VarList; BOOLEAN IsFound; UINT8 *ValueAddrOfVar; UINT16 Index; UINT64 QuestionValue; UINT64 UqiValue; EFI_STATUS Status; CHAR8 *ErrorStr; FORM_BROWSER_FORMSET *FormSet; LIST_ENTRY *FormSetLink; UINT64 CurValue; VarList = NULL; Index = 0; ValueAddrOfVar = NULL; QuestionValue = 0; UqiValue = 0; ErrorStr = NULL; Status = EFI_SUCCESS; FormSet = NULL; FormSetLink = NULL; CurValue = 0; // // Search the Variable List by VarStoreId and Offset // IsFound = FALSE; FormSetLink = GetFirstNode (&mFormSetListEntry); while (!IsNull (&mFormSetListEntry, FormSetLink)) { FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink); Status = SearchVarStorage ( CurQuestion, NULL, CurQuestion->VarStoreInfo.VarOffset, FormSet->StorageListHead, (CHAR8 **) &ValueAddrOfVar, &VarList ); if (!EFI_ERROR (Status)) { IsFound = TRUE; break; } FormSetLink = GetNextNode (&mFormSetListEntry, FormSetLink); } if (!IsFound) { if (CurUqiList->Header.ScriptsLine == 0) { printf ("Error. The question in the command line doesn't store value by EFI_VARSTORE_IFR or EFI_VARSTORE_IFR_EFI.\n"); } else { 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); } return EFI_ABORTED; } // // Check the length of variable value // if (CurQuestion->QuestionReferToBitField) { GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)&QuestionValue); } else { switch (CurQuestion->StorageWidth) { case sizeof (UINT8): QuestionValue = *(UINT8 *)ValueAddrOfVar; break; case sizeof (UINT16): QuestionValue = *(UINT16 *)ValueAddrOfVar; break; case sizeof (UINT32): QuestionValue = *(UINT32 *)ValueAddrOfVar; break; case sizeof (UINT64): QuestionValue = *(UINT64 *)ValueAddrOfVar; break; default: // // The storage width of ORDERED_LIST may not be any type above. // ; break; } } UqiValue = *(UINT64 *)CurUqiList->Header.Value; CurUqiList->SameOrNot = TRUE; // // Check and set the checkbox value // if (CurQuestion->Operand == EFI_IFR_CHECKBOX_OP) { if ((UqiValue != 0) && (UqiValue != 1)) { CurUqiList->ErrorOrNot = TRUE; CurUqiList->SameOrNot = FALSE; CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8)); if (CurUqiList->Error == NULL) { printf ("Fail to allocate memory!\n"); return EFI_ABORTED; } memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH); sprintf (CurUqiList->Error, "Error. The updated value of CHECKBOX 0x%llx is invalid.\n", (unsigned long long) UqiValue); if (CurQuestion->QuestionReferToBitField) { GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue); } else { memcpy ( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); } } else { if (QuestionValue != UqiValue) { if (CurQuestion->QuestionReferToBitField) { GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue); SetBitsQuestionValue (CurQuestion, ValueAddrOfVar, *(UINT32*)CurUqiList->Header.Value); } else { memcpy ( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); memcpy ( ValueAddrOfVar, CurUqiList->Header.Value, CurQuestion->StorageWidth ); } CurUqiList->SameOrNot = FALSE; } } } if (CurQuestion->Operand == EFI_IFR_STRING_OP) { if ((FceStrLen((wchar_t *)CurUqiList->Header.Value) + 1) * 2 > CurQuestion->StorageWidth) { CurUqiList->ErrorOrNot = TRUE; CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8)); if (CurUqiList->Error == NULL) { printf ("Fail to allocate memory!\n"); return EFI_ABORTED; } memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH); sprintf (CurUqiList->Error, "Error. The updated value of STRING exceed its Size.\n"); memcpy ( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); } else { if (memcmp((CHAR8 *)CurUqiList->Header.Value, ValueAddrOfVar, CurQuestion->StorageWidth) != 0) { memcpy( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); memcpy( ValueAddrOfVar, CurUqiList->Header.Value, CurQuestion->StorageWidth ); CurUqiList->SameOrNot = FALSE; } } } // // Check and set the NUMERIC value // if (CurQuestion->Operand == EFI_IFR_NUMERIC_OP) { if ((UqiValue < CurQuestion->Minimum) || (UqiValue > CurQuestion->Maximum)) { CurUqiList->ErrorOrNot = TRUE; CurUqiList->SameOrNot = FALSE; CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8)); if (CurUqiList->Error == NULL) { printf ("Fail to allocate memory!\n"); return EFI_ABORTED; } memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH); sprintf (CurUqiList->Error, "Error. The updated value of NUMERIC 0x%llx is invalid.\n", (unsigned long long) UqiValue); if (CurQuestion->QuestionReferToBitField) { GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue); } else { memcpy ( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); } } else { if (QuestionValue != UqiValue) { if (CurQuestion->QuestionReferToBitField) { GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue); SetBitsQuestionValue (CurQuestion, ValueAddrOfVar, *(UINT32*)CurUqiList->Header.Value); } else { memcpy ( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); memcpy ( ValueAddrOfVar, CurUqiList->Header.Value, CurQuestion->StorageWidth ); } CurUqiList->SameOrNot = FALSE; } } } // // Check and set the ONE_OF value // if (CurQuestion->Operand == EFI_IFR_ONE_OF_OP) { if (CheckOneOfParamError (CurQuestion, UqiValue)) { CurUqiList->ErrorOrNot = TRUE; CurUqiList->SameOrNot = FALSE; CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8)); if (CurUqiList->Error == NULL) { printf ("Fail to allocate memory!\n"); return EFI_ABORTED; } memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH); sprintf (CurUqiList->Error, "Error. The updated ONE_OF value 0x%llx is invalid.\n", (unsigned long long) UqiValue); if (CurQuestion->QuestionReferToBitField) { GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue); } else { memcpy ( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); } } else { if (QuestionValue != UqiValue) { if (CurQuestion->QuestionReferToBitField) { GetBitsQuestionValue (CurQuestion, ValueAddrOfVar, (UINT32*)CurUqiList->Header.DiffValue); SetBitsQuestionValue (CurQuestion, ValueAddrOfVar, *(UINT32*)CurUqiList->Header.Value); } else { memcpy ( CurUqiList->Header.DiffValue, ValueAddrOfVar, CurQuestion->StorageWidth ); memcpy ( ValueAddrOfVar, CurUqiList->Header.Value, CurQuestion->StorageWidth ); } CurUqiList->SameOrNot = FALSE; } } } // // Check and set the ORDER_LIST value // if (CurQuestion->Operand == EFI_IFR_ORDERED_LIST_OP) { // // Synchronize the MaxContainers value // *CurUqiList->Header.DiffValue = (UINT8)CurQuestion->MaxContainers; if (CheckOrderParamError (CurQuestion, (CHAR8 *)CurUqiList->Header.Value)) { CurUqiList->ErrorOrNot = TRUE; CurUqiList->SameOrNot = FALSE; CurUqiList->Error = malloc (ERROR_INFO_LENGTH * sizeof (CHAR8)); if (CurUqiList->Error == NULL) { printf ("Fail to allocate memory!\n"); return EFI_ABORTED; } memset (CurUqiList->Error, 0, ERROR_INFO_LENGTH); ErrorStr = CurUqiList->Error; sprintf (ErrorStr, "Error. The updated NORDERED_LIST value "); ErrorStr = ErrorStr + strlen ("Error. The updated NORDERED_LIST value "); for (Index = 0; Index < CurQuestion->StorageWidth; Index++) { sprintf (ErrorStr, "%02x ", *(CurUqiList->Header.Value + Index + 1)); ErrorStr +=3; } sprintf (ErrorStr, "is invalid.\n"); memcpy ( CurUqiList->Header.DiffValue + 1, ValueAddrOfVar, CurQuestion->StorageWidth ); } else { for (Index = 0; Index < CurQuestion->StorageWidth/CurQuestion->MaxContainers; Index++) { CurValue = 0; memcpy ( &CurValue, (ValueAddrOfVar + Index * CurQuestion->StorageWidth/CurQuestion->MaxContainers), CurQuestion->StorageWidth/CurQuestion->MaxContainers ); if (CurValue != *((UINT64 *)CurUqiList->Header.Value + Index + 1)) { CurUqiList->SameOrNot = FALSE; break; } } if (!CurUqiList->SameOrNot) { memcpy ( CurUqiList->Header.DiffValue + 1, ValueAddrOfVar, CurQuestion->StorageWidth ); for (Index = 0; Index < CurQuestion->MaxContainers; Index++) { switch (CurQuestion->StorageWidth/CurQuestion->MaxContainers) { case sizeof (UINT8): *((UINT8 *)ValueAddrOfVar + Index) = *(UINT8 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index); break; case sizeof (UINT16): *((UINT16 *)ValueAddrOfVar + Index) = *(UINT16 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index); break; case sizeof (UINT32): *((UINT32 *)ValueAddrOfVar + Index) = *(UINT32 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index); break; case sizeof (UINT64): *((UINT64 *)ValueAddrOfVar + Index) = *((UINT64 *)CurUqiList->Header.Value + 1 + Index); break; default: *((UINT8 *)ValueAddrOfVar + Index) = *(UINT8 *)((UINT64 *)CurUqiList->Header.Value + 1 + Index); break; } } // // Update the vaule of ORDERED_LIST according to its size // CurUqiList->Header.Value = (UINT8 *)((UINT64 *)CurUqiList->Header.Value); memcpy ( CurUqiList->Header.Value + 1, ValueAddrOfVar, CurQuestion->StorageWidth ); } } } return EFI_SUCCESS; } /** Parse and set the quick configure information by the command line. Read the UQI Config information from command line directly, and then compare it with the value in VarList. Update the Update flag in Varlist. @param UqiList The pointer to the uqi list @param DefaultId The default Id. @param PlatformId The platform Id. @retval EFI_SUCCESS It was complete successfully @retval EFI_UNSUPPORTED Update a read-only value @return EFI_ABORTED An error occurred **/ static EFI_STATUS SetUqiParameters ( IN UQI_PARAM_LIST *UqiList, IN UINT16 DefaultId, IN UINT64 PlatformId ) { FORM_BROWSER_FORMSET *FormSet; LIST_ENTRY *FormSetLink; FORM_BROWSER_FORM *Form; LIST_ENTRY *FormLink; FORM_BROWSER_STATEMENT *Question; LIST_ENTRY *QuestionLink; LIST_ENTRY *FormSetEntryListHead; UQI_PARAM_LIST *CurUqiList; FormSet = NULL; FormSetLink = NULL; Form = NULL; FormLink = NULL; Question = NULL; QuestionLink = NULL; FormSetEntryListHead = &mFormSetListEntry; FormSetLink = GetFirstNode (FormSetEntryListHead); while (!IsNull (FormSetEntryListHead, FormSetLink)) { FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink); // // Parse all forms in formset // FormLink = GetFirstNode (&FormSet->FormListHead); while (!IsNull (&FormSet->FormListHead, FormLink)) { Form = FORM_BROWSER_FORM_FROM_LINK (FormLink); // // Parse five kinds of Questions in Form // QuestionLink = GetFirstNode (&Form->StatementListHead); while (!IsNull (&Form->StatementListHead, QuestionLink)) { Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink); QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink); // // Parse five kinds of Questions in Form // if ((Question->Operand == EFI_IFR_ONE_OF_OP) || (Question->Operand == EFI_IFR_NUMERIC_OP) || (Question->Operand == EFI_IFR_CHECKBOX_OP) || (Question->Operand == EFI_IFR_ORDERED_LIST_OP) || (Question->Operand == EFI_IFR_STRING_OP) ) { if (mMultiPlatformParam.MultiPlatformOrNot) { // // Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode // if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) { continue; } if ((Question->Type == EFI_IFR_VARSTORE_EFI_OP) && Question->NewEfiVarstore && ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) { continue; } } CurUqiList = UqiList; while (CurUqiList != NULL) { if ((PlatformId == CurUqiList->Header.PlatformId[0]) && (DefaultId == CurUqiList->Header.DefaultId[0]) && CompareUqiHeader (&(Question->Uqi), &(CurUqiList->Header)) ) { // // Add further check to avoid a case that there are many options with a // same UQI (en-Us), but always returns the first one. // if (!CurUqiList->ParseOrNot) { CurUqiList->ParseOrNot = TRUE; break; } } CurUqiList = CurUqiList->Next; } if (CurUqiList != NULL) { SetUqiParametersWithQuestion (CurUqiList, DefaultId, PlatformId, Question); } } } FormLink = GetNextNode (&FormSet->FormListHead, FormLink); } FormSetLink = GetNextNode (FormSetEntryListHead, FormSetLink); } return EFI_SUCCESS; } /** Set question value per UqiList. @param UqiList The pointer to the uqi list @param DefaultId The default Id. @param PlatformId The platform Id. **/ VOID SetUqiParametersMultiMode ( IN UQI_PARAM_LIST *UqiList, IN UINT16 DefaultId, IN UINT64 PlatformId ) { UQI_PARAM_LIST *CurUqiList; CurUqiList = UqiList; while (CurUqiList != NULL) { if ((CurUqiList->ParseOrNot == FALSE) && (PlatformId == CurUqiList->Header.PlatformId[0]) && (DefaultId == CurUqiList->Header.DefaultId[0]) ) { CurUqiList->ParseOrNot = TRUE; if (CurUqiList->Header.Question != NULL) { SetUqiParametersWithQuestion (CurUqiList, DefaultId, PlatformId, CurUqiList->Header.Question); } } CurUqiList = CurUqiList->Next; } } /** Find the matched question for each UQI string in UqiList **/ EFI_STATUS ScanUqiFullList ( IN UQI_PARAM_LIST *UqiList ) { FORM_BROWSER_FORMSET *FormSet; LIST_ENTRY *FormSetLink; FORM_BROWSER_FORM *Form; LIST_ENTRY *FormLink; FORM_BROWSER_STATEMENT *Question; LIST_ENTRY *QuestionLink; LIST_ENTRY *FormSetEntryListHead; UQI_PARAM_LIST *CurUqiList; UINT64 PlatformId; UINT16 DefaultId; if (UqiList == NULL) { return EFI_SUCCESS; } FormSet = NULL; FormSetLink = NULL; Form = NULL; FormLink = NULL; Question = NULL; QuestionLink = NULL; FormSetEntryListHead = &mFormSetListEntry; FormSetLink = FormSetEntryListHead->ForwardLink; while (FormSetEntryListHead != FormSetLink) { FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink); // // Parse all forms in formset // FormLink = FormSet->FormListHead.ForwardLink; while (&FormSet->FormListHead != FormLink) { Form = FORM_BROWSER_FORM_FROM_LINK (FormLink); // // Parse five kinds of Questions in Form // QuestionLink = Form->StatementListHead.ForwardLink; while (&Form->StatementListHead != QuestionLink) { Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink); QuestionLink = QuestionLink->ForwardLink; // // Parse five kinds of Questions in Form // if ((Question->Operand == EFI_IFR_ONE_OF_OP) || (Question->Operand == EFI_IFR_NUMERIC_OP) || (Question->Operand == EFI_IFR_CHECKBOX_OP) || (Question->Operand == EFI_IFR_ORDERED_LIST_OP) || (Question->Operand == EFI_IFR_STRING_OP) ) { // // Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode // if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) { continue; } else if (Question->NewEfiVarstore && ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) { continue; } CurUqiList = UqiList; PlatformId = 0xFFFFFFFF; DefaultId = 0xFFFF; while (CurUqiList != NULL) { if ((CurUqiList->Header.Question == NULL) && CompareUqiHeader (&(Question->Uqi), &(CurUqiList->Header)) && ((PlatformId != CurUqiList->Header.PlatformId[0]) || (DefaultId != CurUqiList->Header.DefaultId[0])) ) { CurUqiList->Header.Question = Question; PlatformId = CurUqiList->Header.PlatformId[0]; DefaultId = CurUqiList->Header.DefaultId[0]; } CurUqiList = CurUqiList->Next; } } } FormLink = FormLink->ForwardLink; } FormSetLink = FormSetLink->ForwardLink; } return EFI_SUCCESS; } /** Create and insert the UQI Node to the UQI parameter list. @retval Node address If successed, return the node address. @retval NULL An error occurred. **/ static UQI_PARAM_LIST * CreateInsertUqiNode ( ) { UQI_PARAM_LIST *Node; Node = (UQI_PARAM_LIST *) malloc (sizeof (UQI_PARAM_LIST)); if (Node == NULL) { return NULL; } memset (Node, 0, sizeof (UQI_PARAM_LIST)); if (mUqiList == NULL) { mUqiList = Node; } else { mLastUqiList->Next = Node; } mLastUqiList = Node; return Node; } /** Parse the first part of QUI string @param **argv[] The dual array pointer to the parameters. @param Number The pointer to the number of the first character of UQI. @param Buffer The buffer to store the first part of UQI. @retval EFI_SUCCESS Parse the QUI parameters successfully. @retval EFI_INVALID_PARAMETER An error occurred. **/ static EFI_STATUS ParseFirstpartOfUqi ( IN CHAR8 **argv[], OUT UINT32 *Number, OUT UINT16 **Buffer ) { UINT32 Index; Index = 0; *Number = (UINT32)StrToDec ((*argv)[0]); if ((*Number <= 0) || (*Number > MAX_QUI_PARAM_LEN)) { printf ("Error. Invalid UQI.\n"); return EFI_INVALID_PARAMETER; } *Buffer = malloc ((*Number + 1) * sizeof (CHAR16)); assert (*Buffer != NULL); memset (*Buffer, 0, (*Number + 1) * sizeof (CHAR16)); for (Index = 0; Index < *Number; Index++) { if (StrToDec ((*argv)[Index]) > 0xff) { printf ("Error. Invalid UQI.\n"); return EFI_INVALID_PARAMETER; } *(*Buffer + Index) = (UINT16)StrToDec ((*argv)[Index + 1]); } return EFI_SUCCESS; } /** Parse the QUI input parameters from the command line @param argc The pointer to the number of input parameters. @param **argv[] The dual array pointer to the parameters. @retval EFI_SUCCESS Parse the QUI parameters successfully. @retval EFI_INVALID_PARAMETER An error occurred. **/ static EFI_STATUS ParseUqiParam ( IN UINT32 *argc, IN CHAR8 **argv[] ) { UINT32 Index; UQI_PARAM_LIST *UqiNode; EFI_STATUS Status; Index = 0; UqiNode = NULL; if (*argc < 4) { printf ("Error. The correct command is 'FCE updateq -i -o '.\n"); return EFI_INVALID_PARAMETER; } UqiNode = CreateInsertUqiNode (); assert (UqiNode != NULL); UqiNode->Header.DefaultId = (UINT16 *) calloc (1, sizeof (UINT16)); UqiNode->Header.PlatformId = (UINT64 *) calloc (1, sizeof (UINT64)); Status = ParseFirstpartOfUqi (argv, &(UqiNode->Header.HexNum), &(UqiNode->Header.Data)); if (EFI_ERROR (Status)) { return Status; } *argc -= (UqiNode->Header.HexNum + 1); *argv += UqiNode->Header.HexNum + 1; // // Parse the TYPE and value // if (strcmp ("ONE_OF", (*argv)[0]) == 0) { UqiNode->Header.Type = ONE_OF; } else if (strcmp ("NUMERIC", (*argv)[0]) == 0) { UqiNode->Header.Type = NUMERIC; } else if (strcmp ("CHECKBOX", (*argv)[0]) == 0) { UqiNode->Header.Type = CHECKBOX; } else if (strcmp ("STRING", (*argv)[0]) == 0) { UqiNode->Header.Type = STRING; } else if (strcmp ("ORDERED_LIST", (*argv)[0]) == 0) { UqiNode->Header.Type = ORDERED_LIST; } else { printf ("Error. The correct command is 'FCE updateq -i -o '.\n"); return EFI_INVALID_PARAMETER; } *argc -= 1; *argv += 1; // // Get the value according to the type of questions. // switch (UqiNode->Header.Type) { case ONE_OF: case NUMERIC: case CHECKBOX: UqiNode->Header.Value = malloc (sizeof (UINT64)); if (UqiNode->Header.Value == NULL) { printf ("Fali to allocate memory!\n"); return EFI_OUT_OF_RESOURCES; } memset (UqiNode->Header.Value, 0, sizeof (UINT64)); UqiNode->Header.DiffValue = malloc (sizeof (UINT64)); if (UqiNode->Header.DiffValue == NULL) { printf ("Fali to allocate memory!\n"); return EFI_OUT_OF_RESOURCES; } memset ( UqiNode->Header.DiffValue, 0, sizeof (UINT64) ); *(UINT64 *)(UqiNode->Header.Value) = (UINT64)StrToDec ((*argv)[0]); break; case ORDERED_LIST: UqiNode->Header.Value = malloc (((UINTN)StrToDec ((*argv)[0]) + 1) * sizeof (UINT64)); if (UqiNode->Header.Value == NULL) { printf ("Fali to allocate memory!\n"); return EFI_OUT_OF_RESOURCES; } memset ( UqiNode->Header.Value, 0, (UINTN)StrToDec(((*argv)[0]) + 1) * sizeof (UINT64) ); UqiNode->Header.DiffValue = malloc (((UINTN)StrToDec ((*argv)[0]) + 1) * sizeof (UINT64)); if (UqiNode->Header.DiffValue == NULL) { printf ("Fali to allocate memory!\n"); return EFI_OUT_OF_RESOURCES; } memset ( UqiNode->Header.DiffValue, 0, (UINTN)(StrToDec ((*argv)[0]) + 1) * sizeof (UINT64) ); *UqiNode->Header.Value = (UINT8)StrToDec ((*argv)[0]); for (Index = 1; Index <= StrToDec ((*argv)[0]); Index++) { *((UINT64 *)UqiNode->Header.Value + Index) = StrToDec ((*argv)[Index]); } *argc -= (UINTN)StrToDec ((*argv)[0]); *argv += (UINTN)StrToDec ((*argv)[0]); break; default: break; } *argc -= 1; *argv += 1; if (*argc > 0) { printf ("Error. The correct command is 'FCE updateq -i -o '.\n"); return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; } /** Parse the input Fd file, and get the file name according to the FILETYPE. @param FdName The Name of Fd file @param FILETYPE The type of Fd file @return EFI_SUCCESS Get the file name successfully @return EFI_ABORTED An error occurred. **/ static EFI_STATUS ParseInFile ( IN CHAR8 *FdName, IN FILETYPE Type ) { FILE *Fptr; Fptr = NULL; if ((Type == INFD) && ((FdName == NULL) || (Fptr = fopen (FdName, "r")) == NULL)) { if (FdName != NULL) { printf ("Error: The file doesn't exist '%s'\n", FdName); } return EFI_ABORTED; } if ((Type == OUTFD) && (FdName == NULL) ) { printf ("Error: The name is NULL.\n"); return EFI_ABORTED; } if ((Type == SETUPTXT) && (FdName == NULL) ) { printf ("Error: The