Home | History | Annotate | Download | only in FrameworkHiiOnUefiHiiThunk
      1 /** @file
      2 Implement Functions to convert IFR Opcode in format defined in Framework HII specification to
      3 format defined in UEFI HII Specification.
      4 
      5 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "HiiDatabase.h"
     17 #include "UefiIfrDefault.h"
     18 
     19 /**
     20   The dynamic creation of these opcodes is supported in Framework HII modules.
     21   Therefore, Framework HII Thunk module only map these opcode between Framework
     22   HII's definitions to UEFI HII's.
     23 **/
     24 typedef struct {
     25   UINT8 FrameworkIfrOp;
     26   UINT8 UefiIfrOp;
     27 } IFR_OPCODE_MAP;
     28 
     29 IFR_OPCODE_MAP QuestionOpcodeMap[] = {
     30   { FRAMEWORK_EFI_IFR_ONE_OF_OP,        EFI_IFR_ONE_OF_OP},
     31   { FRAMEWORK_EFI_IFR_CHECKBOX_OP,      EFI_IFR_CHECKBOX_OP},
     32   { FRAMEWORK_EFI_IFR_NUMERIC_OP,       EFI_IFR_NUMERIC_OP},
     33   { FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP, EFI_IFR_ONE_OF_OPTION_OP},
     34   { FRAMEWORK_EFI_IFR_ORDERED_LIST_OP,  EFI_IFR_ORDERED_LIST_OP}
     35 };
     36 
     37 /**
     38   Translate a Framework Question Opcode to UEFI Question Opcode.
     39 
     40   @param FwOp     Framework Opcode.
     41   @param UefiOp   UEFI Opcode.
     42 
     43   @retval     EFI_SUCCESS     The UEFI opcode is found and returned.
     44   @retval     EFI_NOT_FOUND   The UEFI opcode is not found.
     45 **/
     46 EFI_STATUS
     47 QuestionOpFwToUefi (
     48   IN            UINT8   FwOp,
     49   OUT           UINT8   *UefiOp
     50   )
     51 {
     52   UINTN       Index;
     53 
     54   for (Index = 0; Index < sizeof (QuestionOpcodeMap) / sizeof (QuestionOpcodeMap[0]); Index++) {
     55     if (FwOp == QuestionOpcodeMap[Index].FrameworkIfrOp) {
     56       *UefiOp = QuestionOpcodeMap[Index].UefiIfrOp;
     57       return EFI_SUCCESS;
     58     }
     59   }
     60 
     61   *UefiOp = (UINT8) (EFI_IFR_LAST_OPCODE + 1);
     62   return EFI_NOT_FOUND;
     63 }
     64 
     65 /**
     66   Translate a Framework Question ID to UEFI Question ID.
     67 
     68   @param FormSet   FormSet context
     69   @param FwOpCode  Framework Opcode
     70   @param FwQId     Framework Question Id
     71   @param UefiQId   UEFI Question ID.
     72 
     73   @retval     EFI_SUCCESS     The UEFI Question Id is found and returned.
     74   @retval     EFI_NOT_FOUND   The UEFI Question Id is not found.
     75 **/
     76 EFI_STATUS
     77 FwQIdToUefiQId (
     78   IN  CONST FORM_BROWSER_FORMSET *FormSet,
     79   IN  UINT8                      FwOpCode,
     80   IN  UINT16                     FwQId,
     81   OUT UINT16                     *UefiQId
     82   )
     83 {
     84   LIST_ENTRY             *FormList;
     85   LIST_ENTRY             *StatementList;
     86   FORM_BROWSER_FORM      *Form;
     87   FORM_BROWSER_STATEMENT *Statement;
     88   FORM_BROWSER_STATEMENT *StatementFound;
     89   EFI_STATUS             Status;
     90   UINT8                  UefiOp;
     91 
     92 
     93   *UefiQId = 0;
     94   StatementFound = NULL;
     95 
     96   FormList = GetFirstNode (&FormSet->FormListHead);
     97 
     98   while (!IsNull (&FormSet->FormListHead, FormList)) {
     99     Form = FORM_BROWSER_FORM_FROM_LINK (FormList);
    100 
    101     StatementList = GetFirstNode (&Form->StatementListHead);
    102 
    103     while (!IsNull (&Form->StatementListHead, StatementList)) {
    104       Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);
    105       if (Statement->VarStoreId != 0 && Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER) {
    106         if (FwQId == Statement->VarStoreInfo.VarOffset) {
    107           Status = QuestionOpFwToUefi (FwOpCode, &UefiOp);
    108           ASSERT_EFI_ERROR (Status);
    109 
    110           if ((UefiOp == Statement->Operand) && (FormSet->DefaultVarStoreId == Statement->VarStoreId)) {
    111             //
    112             // If ASSERT here, the Framework VFR file has two Questions with all three attibutes the same:
    113             // 1) Same Question Type,
    114             // 2) Same Variable Storage
    115             // 3) Refering to the Same offset in Variable Map (NvMap).
    116             // This is ambigurity as FwQIdToUefiQId () can't find which UEFI Question
    117             // ID to return.
    118             //
    119             // One possible solution is to remove the one of the duplicated questions in this Form Set.
    120             //
    121             ASSERT (StatementFound == NULL);
    122             StatementFound= Statement;
    123 
    124             //
    125             // Continue the search to check if the Form Set contains more than one questins that has the 3 attributes
    126             // with same value.
    127             //
    128           }
    129         }
    130       }
    131 
    132       StatementList = GetNextNode (&Form->StatementListHead, StatementList);
    133     }
    134 
    135     FormList = GetNextNode (&FormSet->FormListHead, FormList);
    136   }
    137 
    138   if (StatementFound != NULL) {
    139     *UefiQId = StatementFound->QuestionId;
    140     return EFI_SUCCESS;
    141   }
    142 
    143   return EFI_NOT_FOUND;
    144 }
    145 
    146 /**
    147   Assign a Question ID.
    148 
    149   If FwQuestionId is 0, then assign a new question ID. The new question ID
    150   is MaxQuestionId incremented by 1. The MaxQuestionId of FormSet is also
    151   incremented by 1.
    152 
    153   If FwQuestionId is not 0, then it is used as the Framework Question ID.
    154 
    155   @param FwQuestionId
    156   @param FormSet
    157 
    158   @return The Framework Question ID.
    159 **/
    160 EFI_QUESTION_ID
    161 AssignQuestionId (
    162   IN  UINT16                      FwQuestionId,
    163   IN        FORM_BROWSER_FORMSET  *FormSet
    164   )
    165 {
    166   if (FwQuestionId == 0) {
    167     FormSet->MaxQuestionId++;
    168     return FormSet->MaxQuestionId;
    169   } else {
    170     return FwQuestionId;
    171   }
    172 }
    173 
    174 /**
    175   Create UEFI HII Text Opcode from a Framework HII Text Opcode.
    176 
    177   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    178   @param FwOpcode              The input Framework Opcode.
    179 
    180   @retval NULL   There is not enough space left in Buffer to add the opcode.
    181   @retval Other  A pointer to the created opcode.
    182 
    183 **/
    184 UINT8 *
    185 F2UCreateTextOpCode (
    186   IN OUT   VOID                        *UefiUpdateDataHandle,
    187   IN CONST FRAMEWORK_EFI_IFR_TEXT      *FwOpcode
    188   )
    189 {
    190   EFI_IFR_TEXT      UTextOpCode;
    191 
    192   if ((FwOpcode->Flags & EFI_IFR_FLAG_INTERACTIVE) == 0) {
    193     ZeroMem (&UTextOpCode, sizeof(UTextOpCode));
    194 
    195     UTextOpCode.Header.OpCode = EFI_IFR_TEXT_OP;
    196     UTextOpCode.Header.Length = (UINT8) sizeof (EFI_IFR_TEXT);
    197 
    198     UTextOpCode.Statement.Help   = FwOpcode->Help;
    199 
    200     UTextOpCode.Statement.Prompt = FwOpcode->Text;
    201     UTextOpCode.TextTwo          = FwOpcode->TextTwo;
    202 
    203     return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UTextOpCode, sizeof(UTextOpCode));
    204   } else {
    205     //
    206     // Iteractive Text Opcode is EFI_IFR_ACTION
    207     //
    208     return HiiCreateActionOpCode (UefiUpdateDataHandle, FwOpcode->Key, FwOpcode->Text, FwOpcode->Help, EFI_IFR_FLAG_CALLBACK, 0);
    209   }
    210 }
    211 
    212 /**
    213   Create UEFI HII Reference Opcode from a Framework HII Reference Opcode.
    214 
    215   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    216   @param FwOpcode              The input Framework Opcode.
    217 
    218   @retval NULL   There is not enough space left in Buffer to add the opcode.
    219   @retval Other  A pointer to the created opcode.
    220 
    221 **/
    222 UINT8 *
    223 F2UCreateReferenceOpCode (
    224   IN OUT   VOID                        *UefiUpdateDataHandle,
    225   IN CONST FRAMEWORK_EFI_IFR_REF       *FwOpcode
    226   )
    227 {
    228   EFI_IFR_REF UOpcode;
    229 
    230   ZeroMem (&UOpcode, sizeof(UOpcode));
    231 
    232   UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
    233   UOpcode.Header.OpCode = EFI_IFR_REF_OP;
    234 
    235   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
    236   UOpcode.Question.Header.Help = FwOpcode->Help;
    237   UOpcode.Question.QuestionId = FwOpcode->Key;
    238 
    239   UOpcode.FormId = FwOpcode->FormId;
    240 
    241   //
    242   // We only map EFI_IFR_FLAG_INTERACTIVE and EFI_IFR_FLAG_RESET_REQUIRED to
    243   // UEFI IFR Opcode flags. The rest flags are obsolete.
    244   //
    245   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));
    246 
    247   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
    248 }
    249 
    250 /**
    251   Create UEFI HII "One Of Option" Opcode from a Framework HII "One Of Option" Opcode.
    252 
    253   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    254   @param FwOpcode              The input Framework Opcode.
    255   @param Width                 The size of the One Of Option. 1 bytes or 2 bytes.
    256 
    257   @retval NULL   There is not enough space left in Buffer to add the opcode.
    258   @retval Other  A pointer to the created opcode.
    259 
    260 **/
    261 UINT8 *
    262 F2UCreateOneOfOptionOpCode (
    263   IN OUT   VOID                               *UefiUpdateDataHandle,
    264   IN CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION    *FwOpcode,
    265   IN       UINTN                              Width
    266   )
    267 {
    268   EFI_IFR_ONE_OF_OPTION UOpcode;
    269 
    270   ZeroMem (&UOpcode, sizeof(UOpcode));
    271 
    272   UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
    273   UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
    274 
    275   UOpcode.Option        = FwOpcode->Option;
    276   CopyMem (&UOpcode.Value.u8, &FwOpcode->Value, Width);
    277 
    278   //
    279   // #define EFI_IFR_FLAG_DEFAULT           0x01
    280   // #define EFI_IFR_FLAG_MANUFACTURING     0x02
    281   // #define EFI_IFR_OPTION_DEFAULT                   0x10
    282   // #define EFI_IFR_OPTION_DEFAULT_MFG               0x20
    283   //
    284   UOpcode.Flags = (UINT8) (UOpcode.Flags  | (FwOpcode->Flags & (EFI_IFR_FLAG_DEFAULT | EFI_IFR_FLAG_MANUFACTURING)) << 4);
    285 
    286   switch (Width) {
    287     case 1:
    288       UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_8;
    289       break;
    290 
    291     case 2:
    292       UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_16;
    293       break;
    294 
    295     default:
    296       ASSERT (FALSE);
    297       return NULL;
    298   }
    299 
    300   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
    301 }
    302 
    303 /**
    304   Create a GUID Opcode EFI_IFR_GUID_OPTIONKEY to map the Framework One Of Option callback key
    305   to a UEFI Question ID. This information is used to invoke the Framework HII Browser Callback
    306   function. The opcode is appened to UefiUpdateDataHandle.
    307 
    308   @param    UefiUpdateDataHandle  The UEFI Update Data buffer.
    309   @param    QuestionId            The UEFI Question ID.
    310   @param    OptionValue           The value of the "One Of Option".
    311   @param    KeyValue              The Framework "One Of Option" callback key.
    312 
    313   @retval NULL   There is not enough space left in Buffer to add the opcode.
    314   @retval Other  A pointer to the created opcode.
    315 **/
    316 UINT8 *
    317 CreateGuidOptionKeyOpCode (
    318   IN OUT   VOID                        *UefiUpdateDataHandle,
    319   IN EFI_QUESTION_ID                   QuestionId,
    320   IN UINT16                            OptionValue,
    321   IN EFI_QUESTION_ID                   KeyValue
    322   )
    323 {
    324   EFI_IFR_GUID_OPTIONKEY              *UOpcode;
    325 
    326   UOpcode = (EFI_IFR_GUID_OPTIONKEY *) HiiCreateGuidOpCode (
    327                                          UefiUpdateDataHandle,
    328                                          &gEfiIfrFrameworkGuid,
    329                                          NULL,
    330                                          sizeof (EFI_IFR_GUID_OPTIONKEY)
    331                                          );
    332 
    333   UOpcode->ExtendOpCode = EFI_IFR_EXTEND_OP_OPTIONKEY;
    334   UOpcode->QuestionId  = QuestionId;
    335   CopyMem (&UOpcode->OptionValue, &OptionValue, sizeof (OptionValue));
    336   UOpcode->KeyValue = KeyValue;
    337 
    338   return (UINT8 *) UOpcode;
    339 }
    340 
    341 /**
    342   Create UEFI HII "One Of" Opcode from a Framework HII "One Of" Opcode.
    343 
    344   @param UefiUpdateDataHandle     The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    345   @param ThunkContext             The HII Thunk Context.
    346   @param FwOpcode                 The input Framework Opcode.
    347   @param NextFwOpcode             Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of
    348                                   the "One Of Option".
    349   @param OpcodeCount              The number of Opcode for the complete Framework "One Of" Opcode.
    350 
    351   @retval NULL   There is not enough space left in Buffer to add the opcode.
    352   @retval Other  A pointer to the created opcode.
    353 
    354 **/
    355 UINT8 *
    356 F2UCreateOneOfOpCode (
    357   IN OUT   VOID                        *UefiUpdateDataHandle,
    358   IN       HII_THUNK_CONTEXT           *ThunkContext,
    359   IN CONST FRAMEWORK_EFI_IFR_ONE_OF    *FwOpcode,
    360   OUT      FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode,
    361   OUT      UINTN                       *OpcodeCount
    362   )
    363 {
    364   EFI_STATUS                          Status;
    365   EFI_IFR_ONE_OF                      UOpcode;
    366   FRAMEWORK_EFI_IFR_OP_HEADER         *FwOpHeader;
    367   FRAMEWORK_EFI_IFR_ONE_OF_OPTION     *FwOneOfOp;
    368   UINT8                               *OpCodeBuffer;
    369   UINT8                               *OneOfOpCodeBuffer;
    370 
    371   ASSERT (NextFwOpcode != NULL);
    372   ASSERT (OpcodeCount != NULL);
    373 
    374   ZeroMem (&UOpcode, sizeof(UOpcode));
    375   *OpcodeCount = 0;
    376 
    377   UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
    378   UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OP;
    379   UOpcode.Header.Scope  = 1;
    380 
    381   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
    382   UOpcode.Question.Header.Help = FwOpcode->Help;
    383   UOpcode.Question.VarStoreId  = ThunkContext->FormSet->DefaultVarStoreId;
    384   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
    385 
    386   //
    387   // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode
    388   //
    389   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
    390   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {
    391     ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);
    392 
    393     FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
    394     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) {
    395       UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
    396 
    397       if (UOpcode.Question.QuestionId == 0) {
    398         Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    399         if (EFI_ERROR (Status)) {
    400           UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);
    401         }
    402       }
    403 
    404     }
    405 
    406     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {
    407       UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;
    408     }
    409 
    410     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
    411   }
    412 
    413 
    414   if (UOpcode.Question.QuestionId == 0) {
    415     //
    416     // Assign QuestionId if still not assigned.
    417     //
    418     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    419     if (EFI_ERROR (Status)) {
    420       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    421     }
    422   }
    423 
    424   OneOfOpCodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof (UOpcode));
    425   if (OneOfOpCodeBuffer == NULL) {
    426     return NULL;
    427   }
    428   *OpcodeCount += 1;
    429 
    430   //
    431   // Go over again the Framework IFR binary to build the UEFI One Of Option opcodes.
    432   //
    433   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
    434   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {
    435 
    436     FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
    437 
    438     OpCodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, FwOpcode->Width);
    439     if (OpCodeBuffer == NULL) {
    440       return NULL;
    441     }
    442 
    443     OpCodeBuffer = CreateGuidOptionKeyOpCode (UefiUpdateDataHandle, UOpcode.Question.QuestionId, FwOneOfOp->Value, FwOneOfOp->Key);
    444     if (OpCodeBuffer == NULL) {
    445       return NULL;
    446     }
    447 
    448     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
    449     *OpcodeCount += 1;
    450   }
    451 
    452   OpCodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);
    453   if (OpCodeBuffer != NULL) {
    454     *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
    455     *OpcodeCount += 1;
    456   }
    457 
    458   return OneOfOpCodeBuffer;
    459 }
    460 
    461 /**
    462   Create UEFI HII "Ordered List" Opcode from a Framework HII "Ordered List" Opcode.
    463 
    464   @param UefiUpdateDataHandle The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    465   @param ThunkContext         The HII Thunk Context.
    466   @param FwOpcode             The input Framework Opcode.
    467   @param NextFwOpcode         Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of
    468                               the "Ordered List".
    469   @param OpcodeCount          The number of Opcode for the complete Framework "Ordered List" Opcode.
    470 
    471   @retval NULL   There is not enough space left in Buffer to add the opcode.
    472   @retval Other  A pointer to the created opcode.
    473 
    474 **/
    475 UINT8 *
    476 F2UCreateOrderedListOpCode (
    477   IN OUT    VOID                          *UefiUpdateDataHandle,
    478   IN       HII_THUNK_CONTEXT              *ThunkContext,
    479   IN CONST FRAMEWORK_EFI_IFR_ORDERED_LIST *FwOpcode,
    480   OUT      FRAMEWORK_EFI_IFR_OP_HEADER    **NextFwOpcode,
    481   OUT      UINTN                          *OpcodeCount
    482   )
    483 {
    484   EFI_IFR_ORDERED_LIST              UOpcode;
    485   EFI_STATUS                        Status;
    486   FRAMEWORK_EFI_IFR_OP_HEADER       *FwOpHeader;
    487   FRAMEWORK_EFI_IFR_ONE_OF_OPTION   *FwOneOfOp;
    488   UINT8                             *OpcodeBuffer;
    489   UINT8                             *OrderListOpCode;
    490 
    491   ZeroMem (&UOpcode, sizeof(UOpcode));
    492   *OpcodeCount = 0;
    493 
    494   UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
    495   UOpcode.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
    496   UOpcode.Header.Scope  = 1;
    497 
    498   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
    499   UOpcode.Question.Header.Help = FwOpcode->Help;
    500   UOpcode.Question.VarStoreId  = ThunkContext->FormSet->DefaultVarStoreId;
    501   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
    502 
    503   UOpcode.MaxContainers = FwOpcode->MaxEntries;
    504 
    505   //
    506   // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode
    507   //
    508   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
    509   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {
    510     ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);
    511 
    512     FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
    513     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) {
    514       UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
    515 
    516       if (UOpcode.Question.QuestionId == 0) {
    517         Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    518         if (EFI_ERROR (Status)) {
    519           UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);
    520         }
    521 
    522       }
    523     }
    524 
    525     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) ==  EFI_IFR_FLAG_RESET_REQUIRED) {
    526       UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;
    527     }
    528 
    529     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
    530   }
    531 
    532   if (UOpcode.Question.QuestionId == 0) {
    533     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    534     if (EFI_ERROR (Status)) {
    535       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    536     }
    537   }
    538 
    539   OrderListOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
    540   if (OrderListOpCode == NULL) {
    541     return NULL;
    542   }
    543   *OpcodeCount += 1;
    544 
    545   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
    546   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {
    547     //
    548     // Each entry of Order List in Framework HII is always 1 byte in size
    549     //
    550     OpcodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, 1);
    551     if (OpcodeBuffer == NULL) {
    552       return NULL;
    553     }
    554     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
    555     *OpcodeCount += 1;
    556   }
    557 
    558   OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);
    559   if (OpcodeBuffer != NULL) {
    560     *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
    561     *OpcodeCount += 1;
    562   }
    563 
    564   return OrderListOpCode;
    565 }
    566 
    567 /**
    568   Create UEFI HII CheckBox Opcode from a Framework HII Checkbox Opcode.
    569 
    570   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    571   @param ThunkContext          The HII Thunk Context.
    572   @param FwOpcode              The input Framework Opcode.
    573 
    574   @retval NULL   There is not enough space left in Buffer to add the opcode.
    575   @retval Other  A pointer to the created opcode.
    576 
    577 **/
    578 UINT8 *
    579 F2UCreateCheckBoxOpCode (
    580   IN OUT   VOID                        *UefiUpdateDataHandle,
    581   IN       HII_THUNK_CONTEXT           *ThunkContext,
    582   IN CONST FRAMEWORK_EFI_IFR_CHECKBOX  *FwOpcode
    583   )
    584 {
    585   EFI_STATUS       Status;
    586   EFI_IFR_CHECKBOX UOpcode;
    587 
    588   ZeroMem (&UOpcode, sizeof(UOpcode));
    589 
    590   UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
    591   UOpcode.Header.OpCode = EFI_IFR_CHECKBOX_OP;
    592 
    593   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
    594   UOpcode.Question.Header.Help = FwOpcode->Help;
    595 
    596   if (FwOpcode->Key == 0) {
    597     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    598     if (EFI_ERROR (Status)) {
    599       //
    600       // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
    601       //
    602       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    603     }
    604   } else {
    605     UOpcode.Question.QuestionId    = FwOpcode->Key;
    606   }
    607 
    608   //
    609   // We map 2 flags:
    610   //      EFI_IFR_FLAG_INTERACTIVE,
    611   //      EFI_IFR_FLAG_RESET_REQUIRED,
    612   // to UEFI IFR Opcode Question flags. The rest flags are obsolete.
    613   //
    614   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));
    615 
    616 
    617   UOpcode.Question.VarStoreId    = ThunkContext->FormSet->DefaultVarStoreId;
    618   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
    619 
    620   //
    621   // We also map these 2 flags:
    622   //      EFI_IFR_FLAG_DEFAULT,
    623   //      EFI_IFR_FLAG_MANUFACTURING,
    624   // to UEFI IFR CheckBox Opcode default flags.
    625   //
    626   UOpcode.Flags           = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_DEFAULT | EFI_IFR_FLAG_MANUFACTURING));
    627 
    628   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
    629 }
    630 
    631 
    632 /**
    633   Create UEFI HII Numeric Opcode from a Framework HII Numeric Opcode.
    634 
    635   @param UefiUpdateDataHandle    The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    636   @param ThunkContext            The HII Thunk Context.
    637   @param FwOpcode                The input Framework Opcode.
    638 
    639   @retval NULL   There is not enough space left in Buffer to add the opcode.
    640   @retval Other  A pointer to the created opcode.
    641 
    642 **/
    643 UINT8 *
    644 F2UCreateNumericOpCode (
    645   IN OUT   VOID                        *UefiUpdateDataHandle,
    646   IN       HII_THUNK_CONTEXT           *ThunkContext,
    647   IN CONST FRAMEWORK_EFI_IFR_NUMERIC   *FwOpcode
    648   )
    649 {
    650   EFI_STATUS      Status;
    651   EFI_IFR_NUMERIC UOpcode;
    652   EFI_IFR_DEFAULT UOpcodeDefault;
    653   UINT8           *NumbericOpCode;
    654   UINT8           *OpcodeBuffer;
    655 
    656   ZeroMem (&UOpcode, sizeof(UOpcode));
    657 
    658   if (FwOpcode->Key == 0) {
    659     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    660     if (EFI_ERROR (Status)) {
    661       //
    662       // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
    663       //
    664       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    665     }
    666   } else {
    667     UOpcode.Question.QuestionId    = FwOpcode->Key;
    668   }
    669 
    670   UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
    671   UOpcode.Header.OpCode = EFI_IFR_NUMERIC_OP;
    672   //
    673   // We need to create a nested default value for the UEFI Numeric Opcode.
    674   // So turn on the scope.
    675   //
    676   UOpcode.Header.Scope = 1;
    677 
    678   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
    679   UOpcode.Question.Header.Help = FwOpcode->Help;
    680 
    681   UOpcode.Question.VarStoreId    = ThunkContext->FormSet->DefaultVarStoreId;
    682   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
    683 
    684   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));
    685 
    686   //
    687   // Framework Numeric values are all in UINT16 and displayed as decimal.
    688   //
    689   UOpcode.data.u16.MinValue = FwOpcode->Minimum;
    690   UOpcode.data.u16.MaxValue = FwOpcode->Maximum;
    691   UOpcode.data.u16.Step = FwOpcode->Step;
    692 
    693   switch (FwOpcode->Width) {
    694     case 1:
    695     {
    696       UOpcode.Flags           =  EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC;
    697       break;
    698     }
    699     case 2:
    700     {
    701       UOpcode.Flags           =  EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC;
    702       break;
    703     }
    704     default:
    705     {
    706       ASSERT (FALSE);
    707       return NULL;
    708     }
    709   }
    710 
    711   NumbericOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
    712   if (NumbericOpCode == NULL) {
    713     return NULL;
    714   }
    715 
    716   //
    717   // We need to create a default value.
    718   //
    719   ZeroMem (&UOpcodeDefault, sizeof (UOpcodeDefault));
    720   UOpcodeDefault.Header.Length = (UINT8) sizeof (UOpcodeDefault);
    721   UOpcodeDefault.Header.OpCode = EFI_IFR_DEFAULT_OP;
    722 
    723   UOpcodeDefault.DefaultId = 0;
    724 
    725   switch (FwOpcode->Width) {
    726     case 1:
    727     {
    728       UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_8;
    729       break;
    730     }
    731     case 2:
    732     {
    733       UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_16;
    734       break;
    735     }
    736   }
    737 
    738   CopyMem (&UOpcodeDefault.Value.u8, &FwOpcode->Default, FwOpcode->Width);
    739 
    740   OpcodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcodeDefault, sizeof(UOpcodeDefault));
    741   if (OpcodeBuffer == NULL) {
    742     return NULL;
    743   }
    744 
    745   OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);
    746   if (OpcodeBuffer == NULL) {
    747     return NULL;
    748   }
    749 
    750   return NumbericOpCode;
    751 }
    752 
    753 
    754 /**
    755   Create UEFI HII String Opcode from a Framework HII String Opcode.
    756 
    757   @param UefiUpdateDataHandle     The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    758   @param ThunkContext             The HII Thunk Context.
    759   @param FwOpcode                 The input Framework Opcode.
    760 
    761   @retval NULL   There is not enough space left in Buffer to add the opcode.
    762   @retval Other  A pointer to the created opcode.
    763 
    764 **/
    765 UINT8 *
    766 F2UCreateStringOpCode (
    767   IN OUT   VOID                        *UefiUpdateDataHandle,
    768   IN       HII_THUNK_CONTEXT           *ThunkContext,
    769   IN CONST FRAMEWORK_EFI_IFR_STRING    *FwOpcode
    770   )
    771 {
    772   EFI_IFR_STRING UOpcode;
    773   EFI_STATUS     Status;
    774 
    775   ZeroMem (&UOpcode, sizeof(UOpcode));
    776 
    777   if (FwOpcode->Key == 0) {
    778     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
    779     if (EFI_ERROR (Status)) {
    780       //
    781       // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
    782       //
    783       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
    784     }
    785   } else {
    786     UOpcode.Question.QuestionId    = FwOpcode->Key;
    787   }
    788 
    789   UOpcode.Header.Length = (UINT8) sizeof (UOpcode);
    790   UOpcode.Header.OpCode = EFI_IFR_STRING_OP;
    791 
    792   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
    793   UOpcode.Question.Header.Help = FwOpcode->Help;
    794 
    795   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));
    796 
    797   UOpcode.Question.VarStoreId    = ThunkContext->FormSet->DefaultVarStoreId;
    798   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
    799 
    800   UOpcode.MinSize = FwOpcode->MinSize;
    801   UOpcode.MaxSize = FwOpcode->MaxSize;
    802   UOpcode.Flags   = EFI_IFR_STRING_MULTI_LINE;
    803 
    804   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));
    805 }
    806 
    807 /**
    808   Create UEFI HII Banner Opcode from a Framework HII Banner Opcode.
    809 
    810   @param UefiUpdateDataHandle     The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.
    811   @param FwOpcode                 The input Framework Opcode.
    812 
    813   @retval NULL   There is not enough space left in Buffer to add the opcode.
    814   @retval Other  A pointer to the created opcode.
    815 
    816 **/
    817 UINT8 *
    818 F2UCreateBannerOpCode (
    819   IN OUT   VOID              *UefiUpdateDataHandle,
    820   IN CONST EFI_IFR_BANNER    *FwOpcode
    821   )
    822 {
    823   EFI_IFR_GUID_BANNER *UOpcode;
    824 
    825   UOpcode = (EFI_IFR_GUID_BANNER *) HiiCreateGuidOpCode (
    826                                       UefiUpdateDataHandle,
    827                                       &gEfiIfrTianoGuid,
    828                                       NULL,
    829                                       sizeof (EFI_IFR_GUID_BANNER)
    830                                       );
    831 
    832   UOpcode->ExtendOpCode = EFI_IFR_EXTEND_OP_BANNER;
    833   UOpcode->Title          = FwOpcode->Title;
    834   UOpcode->LineNumber     = FwOpcode->LineNumber;
    835   UOpcode->Alignment      = FwOpcode->Alignment;
    836 
    837   return (UINT8 *) UOpcode;
    838 }
    839 
    840 /**
    841   Create a Hii Update data Handle used to call IfrLibUpdateForm.
    842 
    843   @param ThunkContext         The HII Thunk Context.
    844   @param FwUpdateData         The Framework Update Data.
    845   @param UefiOpCodeHandle     The UEFI opcode handle.
    846 
    847   @retval EFI_SUCCESS       The UEFI Update Data is created successfully.
    848   @retval EFI_UNSUPPORTED   There is unsupported opcode in FwUpdateData.
    849   @retval EFI_OUT_OF_RESOURCES There is not enough resource.
    850 **/
    851 EFI_STATUS
    852 FwUpdateDataToUefiUpdateData (
    853   IN       HII_THUNK_CONTEXT    *ThunkContext,
    854   IN CONST EFI_HII_UPDATE_DATA  *FwUpdateData,
    855   IN       VOID                 *UefiOpCodeHandle
    856   )
    857 {
    858   FRAMEWORK_EFI_IFR_OP_HEADER          *FwOpCode;
    859   FRAMEWORK_EFI_IFR_OP_HEADER          *NextFwOpCode;
    860   UINTN                                Index;
    861   UINTN                                DataCount;
    862   UINT8                                *OpCodeBuffer;
    863   LIST_ENTRY                           *StorageList;
    864   FORMSET_STORAGE                      *Storage;
    865   FORM_BROWSER_FORMSET                 *FormSet;
    866   CHAR16                               *DefaultVarStoreName;
    867   UINT16                               DefaultVarStoreId;
    868   EFI_IFR_VARSTORE_SELECT              *SelectVarOp;
    869 
    870   FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &FwUpdateData->Data;
    871 
    872   FormSet = ThunkContext->FormSet;
    873   DefaultVarStoreId   = FormSet->DefaultVarStoreId;
    874   DefaultVarStoreName = FormSet->OriginalDefaultVarStoreName;
    875 
    876   for (Index = 0; Index < FwUpdateData->DataCount; Index += DataCount) {
    877     switch (FwOpCode->OpCode) {
    878       case FRAMEWORK_EFI_IFR_SUBTITLE_OP:
    879         OpCodeBuffer = HiiCreateSubTitleOpCode (UefiOpCodeHandle, ((FRAMEWORK_EFI_IFR_SUBTITLE  *) FwOpCode)->SubTitle, 0, 0, 0);
    880         DataCount = 1;
    881         break;
    882 
    883       case FRAMEWORK_EFI_IFR_TEXT_OP:
    884         OpCodeBuffer = F2UCreateTextOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_TEXT  *) FwOpCode);
    885         DataCount = 1;
    886         break;
    887 
    888       case FRAMEWORK_EFI_IFR_REF_OP:
    889         OpCodeBuffer = F2UCreateReferenceOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_REF *) FwOpCode);
    890         DataCount = 1;
    891         break;
    892 
    893       case FRAMEWORK_EFI_IFR_ONE_OF_OP:
    894         OpCodeBuffer = F2UCreateOneOfOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, &NextFwOpCode, &DataCount);
    895         if (OpCodeBuffer != NULL) {
    896           FwOpCode = NextFwOpCode;
    897           //
    898           // FwOpCode is already updated to point to the next opcode.
    899           //
    900           continue;
    901         }
    902         break;
    903 
    904       case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP:
    905         OpCodeBuffer = F2UCreateOrderedListOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, &NextFwOpCode, &DataCount);
    906         if (OpCodeBuffer != NULL) {
    907           FwOpCode = NextFwOpCode;
    908           //
    909           // FwOpCode is already updated to point to the next opcode.
    910           //
    911           continue;
    912         }
    913         break;
    914 
    915       case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
    916         OpCodeBuffer = F2UCreateCheckBoxOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode);
    917         DataCount = 1;
    918         break;
    919 
    920       case FRAMEWORK_EFI_IFR_STRING_OP:
    921         OpCodeBuffer = F2UCreateStringOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode);
    922         DataCount = 1;
    923         break;
    924 
    925       case EFI_IFR_BANNER_OP:
    926         OpCodeBuffer = F2UCreateBannerOpCode (UefiOpCodeHandle, (EFI_IFR_BANNER *) FwOpCode);
    927         DataCount = 1;
    928         break;
    929 
    930       case EFI_IFR_END_ONE_OF_OP:
    931         OpCodeBuffer = HiiCreateEndOpCode (UefiOpCodeHandle);
    932         DataCount = 1;
    933         break;
    934 
    935       case FRAMEWORK_EFI_IFR_NUMERIC_OP:
    936         OpCodeBuffer = F2UCreateNumericOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_NUMERIC *) FwOpCode);
    937         DataCount = 1;
    938         break;
    939 
    940       case EFI_IFR_VARSTORE_SELECT_OP:
    941         OpCodeBuffer = (UINT8 *) FwOpCode;
    942         SelectVarOp  = (EFI_IFR_VARSTORE_SELECT *) FwOpCode;
    943         //
    944         // Check whether the selected VarId is in StorageList.
    945         //
    946         StorageList = GetFirstNode (&FormSet->StorageListHead);
    947         while (!IsNull (&FormSet->StorageListHead, StorageList)) {
    948           Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
    949           if (Storage->VarStoreId == SelectVarOp->VarId) {
    950             break;
    951           }
    952           StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
    953         }
    954         ASSERT (!IsNull (&FormSet->StorageListHead, StorageList));
    955         //
    956         // Change VarStoreId to the selected VarId.
    957         //
    958         FormSet->DefaultVarStoreId = SelectVarOp->VarId;
    959         if (SelectVarOp->VarId == DefaultVarStoreId)  {
    960           FormSet->OriginalDefaultVarStoreName = DefaultVarStoreName;
    961         }
    962         DataCount = 1;
    963         break;
    964 
    965       default:
    966         ASSERT (FALSE);
    967         return EFI_UNSUPPORTED;
    968     }
    969 
    970     if (OpCodeBuffer == NULL) {
    971       return EFI_OUT_OF_RESOURCES;
    972     }
    973 
    974     FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length);
    975   }
    976 
    977   //
    978   // Revert FromSet default varstore ID.
    979   //
    980   FormSet->DefaultVarStoreId           = DefaultVarStoreId;
    981   FormSet->OriginalDefaultVarStoreName = DefaultVarStoreName;
    982   return EFI_SUCCESS;
    983 }
    984 
    985