Home | History | Annotate | Download | only in FrameworkHiiOnUefiHiiThunk
      1 /** @file
      2   Function and Macro defintions for to extract default values from UEFI Form package.
      3 
      4   Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "HiiDatabase.h"
     16 #include "UefiIfrParser.h"
     17 #include "UefiIfrDefault.h"
     18 
     19 //
     20 // Extern Variables
     21 //
     22 extern CONST EFI_HII_DATABASE_PROTOCOL            *mHiiDatabase;
     23 extern CONST EFI_HII_IMAGE_PROTOCOL               *mHiiImageProtocol;
     24 extern CONST EFI_HII_STRING_PROTOCOL              *mHiiStringProtocol;
     25 extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL      *mHiiConfigRoutingProtocol;
     26 
     27 /**
     28   Set the data position at Offset with Width in Node->Buffer based
     29   the value passed in.
     30 
     31   @param  Node                    The Buffer Storage Node.
     32   @param Value                    The input value.
     33   @param Offset                   The offset in Node->Buffer for the update.
     34   @param Width                    The length of the Value.
     35 
     36 **/
     37 VOID
     38 SetNodeBuffer (
     39   OUT UEFI_IFR_BUFFER_STORAGE_NODE        *Node,
     40   IN  CONST   EFI_HII_VALUE               *Value,
     41   IN  UINTN                               Offset,
     42   IN  UINTN                               Width
     43   )
     44 {
     45   ASSERT (Node->Signature == UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE);
     46   ASSERT (Offset + Width <= Node->Size);
     47 
     48   CopyMem (Node->Buffer + Offset, &Value->Value.u8, Width);
     49 }
     50 
     51 
     52 /**
     53   Get question default value, and set it into the match var storage.
     54 
     55   Note Framework 0.92's HII Implementation does not support for default value for these opcodes:
     56   EFI_IFR_ORDERED_LIST_OP:
     57   EFI_IFR_PASSWORD_OP:
     58   EFI_IFR_STRING_OP:
     59 
     60   @param  Question               Question to be set to its default value.
     61   @param  DefaultId              The Class of the default.
     62   @param  VarStoreId             Id of var storage.
     63   @param  Node                   Var storage buffer to store the got default value.
     64 
     65   @retval EFI_SUCCESS            Question is reset to default value.
     66 
     67 **/
     68 EFI_STATUS
     69 GetQuestionDefault (
     70   IN FORM_BROWSER_STATEMENT           *Question,
     71   IN UINT16                           DefaultId,
     72   IN UINT16                           VarStoreId,
     73   OUT UEFI_IFR_BUFFER_STORAGE_NODE    *Node
     74   )
     75 {
     76   EFI_STATUS              Status;
     77   LIST_ENTRY              *Link;
     78   QUESTION_DEFAULT        *Default;
     79   QUESTION_OPTION         *Option;
     80   EFI_HII_VALUE           *HiiValue;
     81 
     82   Status = EFI_SUCCESS;
     83 
     84   //
     85   // Statement don't have storage, skip them
     86   //
     87   if (Question->QuestionId == 0) {
     88     return Status;
     89   }
     90 
     91   if (Question->VarStoreId != VarStoreId) {
     92     return Status;
     93   }
     94 
     95   ASSERT (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER);
     96 
     97   //
     98   // There are three ways to specify default value for a Question:
     99   //  1, use nested EFI_IFR_DEFAULT (highest priority)
    100   //  2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
    101   //  3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
    102   //
    103   HiiValue = &Question->HiiValue;
    104 
    105   //
    106   // EFI_IFR_DEFAULT has highest priority
    107   //
    108   if (!IsListEmpty (&Question->DefaultListHead)) {
    109     Link = GetFirstNode (&Question->DefaultListHead);
    110     while (!IsNull (&Question->DefaultListHead, Link)) {
    111       Default = QUESTION_DEFAULT_FROM_LINK (Link);
    112 
    113       if (Default->DefaultId == DefaultId) {
    114         //
    115         // Default value is embedded in EFI_IFR_DEFAULT
    116         //
    117         CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
    118 
    119         SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
    120         return EFI_SUCCESS;
    121       }
    122 
    123       Link = GetNextNode (&Question->DefaultListHead, Link);
    124     }
    125   }
    126 
    127   //
    128   // EFI_ONE_OF_OPTION
    129   //
    130   if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
    131     if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
    132       //
    133       // OneOfOption could only provide Standard and Manufacturing default
    134       //
    135       Link = GetFirstNode (&Question->OptionListHead);
    136       while (!IsNull (&Question->OptionListHead, Link)) {
    137         Option = QUESTION_OPTION_FROM_LINK (Link);
    138 
    139         if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT)) ||
    140             ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG))
    141            ) {
    142           CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
    143 
    144           SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
    145           return EFI_SUCCESS;
    146         }
    147 
    148         Link = GetNextNode (&Question->OptionListHead, Link);
    149       }
    150     }
    151   }
    152 
    153   //
    154   // EFI_IFR_CHECKBOX - lowest priority
    155   //
    156   if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
    157     if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
    158       //
    159       // Checkbox could only provide Standard and Manufacturing default
    160       //
    161       if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT)) ||
    162           ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG))
    163          ) {
    164         HiiValue->Value.b = TRUE;
    165       } else {
    166         HiiValue->Value.b = FALSE;
    167       }
    168 
    169       SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
    170       return EFI_SUCCESS;
    171     }
    172   }
    173 
    174   return Status;
    175 }
    176 
    177 
    178 /**
    179   Extract the default values from all questions in the input Form,
    180   and set default value into the matched var storage.
    181 
    182   @param  Form                   The Form which to be reset.
    183   @param  DefaultId              The Class of the default.
    184   @param  VarStoreId             Id of var storage.
    185   @param  Node                   Var storage buffer to store the got default value.
    186 
    187   @retval EFI_SUCCESS            The function completed successfully.
    188 
    189 **/
    190 EFI_STATUS
    191 ExtractFormDefault (
    192   IN FORM_BROWSER_FORM                *Form,
    193   IN UINT16                           DefaultId,
    194   IN UINT16                           VarStoreId,
    195   OUT UEFI_IFR_BUFFER_STORAGE_NODE    *Node
    196   )
    197 {
    198   EFI_STATUS              Status;
    199   LIST_ENTRY              *Link;
    200   FORM_BROWSER_STATEMENT  *Question;
    201 
    202   Link = GetFirstNode (&Form->StatementListHead);
    203   while (!IsNull (&Form->StatementListHead, Link)) {
    204     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
    205     //
    206     // Reset Question to its default value
    207     //
    208     Status = GetQuestionDefault (Question, DefaultId, VarStoreId, Node);
    209     if (EFI_ERROR (Status)) {
    210       continue;
    211     }
    212 
    213     Link = GetNextNode (&Form->StatementListHead, Link);
    214   }
    215   return EFI_SUCCESS;
    216 }
    217 
    218 
    219 /**
    220   Destroy all the buffer allocated for the fileds of
    221   UEFI_IFR_BUFFER_STORAGE_NODE. The Node itself
    222   will be freed too.
    223 
    224   @param  Node                Var storage buffer.
    225 
    226 **/
    227 VOID
    228 DestroyDefaultNode (
    229   IN UEFI_IFR_BUFFER_STORAGE_NODE        *Node
    230   )
    231 {
    232   FreePool (Node->Buffer);
    233   FreePool (Node->Name);
    234   FreePool (Node);
    235 }
    236 
    237 
    238 /**
    239   Get the default value for Buffer Type storage named by
    240   a Default Store and a Storage Store from a FormSet.
    241   The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
    242   allocated by this function. It is inserted to the link list.
    243 
    244   @param  DefaultStore           The Default Store.
    245   @param  Storage                The Storage.
    246   @param  FormSet                The Form Set.
    247   @param  UefiDefaultsListHead   The head of link list for the output.
    248 
    249   @retval   EFI_SUCCESS          Successful.
    250 
    251 **/
    252 EFI_STATUS
    253 GetBufferTypeDefaultIdAndStorageId (
    254   IN        FORMSET_DEFAULTSTORE        *DefaultStore,
    255   IN        FORMSET_STORAGE             *Storage,
    256   IN        FORM_BROWSER_FORMSET        *FormSet,
    257   OUT       LIST_ENTRY                  *UefiDefaultsListHead
    258  )
    259 {
    260   UEFI_IFR_BUFFER_STORAGE_NODE        *Node;
    261   LIST_ENTRY              *Link;
    262   FORM_BROWSER_FORM       *Form;
    263   EFI_STATUS              Status;
    264 
    265   Node = AllocateZeroPool (sizeof (UEFI_IFR_BUFFER_STORAGE_NODE));
    266   ASSERT (Node != NULL);
    267 
    268   Node->Signature = UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE;
    269   Node->Name      = AllocateCopyPool (StrSize (Storage->Name), Storage->Name);
    270   Node->DefaultId = DefaultStore->DefaultId;
    271   Node->StoreId   = Storage->VarStoreId;
    272   CopyGuid (&Node->Guid, &Storage->Guid);
    273   Node->Size      = Storage->Size;
    274   Node->Buffer    = AllocateZeroPool (Node->Size);
    275   //
    276   // Extract default from IFR binary
    277   //
    278   Link = GetFirstNode (&FormSet->FormListHead);
    279   while (!IsNull (&FormSet->FormListHead, Link)) {
    280     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
    281 
    282     Status = ExtractFormDefault (Form, DefaultStore->DefaultId, Storage->VarStoreId, Node);
    283     ASSERT_EFI_ERROR (Status);
    284 
    285     Link = GetNextNode (&FormSet->FormListHead, Link);
    286   }
    287 
    288   InsertTailList (UefiDefaultsListHead, &Node->List);
    289 
    290   return EFI_SUCCESS;
    291 }
    292 
    293 
    294 /**
    295   Get the default value for Buffer Type storage named by
    296   a Default Store from a FormSet.
    297   The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
    298   allocated by this function. The output can be multiple instances
    299   of UEFI_IFR_BUFFER_STORAGE_NODE. It is inserted to the link list.
    300 
    301   @param  DefaultStore            The Default Store.
    302   @param  FormSet                  The Form Set.
    303   @param  UefiDefaultsListHead The head of link list for the output.
    304 
    305   @retval   EFI_SUCCESS          Successful.
    306 
    307 **/
    308 EFI_STATUS
    309 GetBufferTypeDefaultId (
    310   IN  FORMSET_DEFAULTSTORE  *DefaultStore,
    311   IN  FORM_BROWSER_FORMSET  *FormSet,
    312   OUT       LIST_ENTRY      *UefiDefaultsListHead
    313   )
    314 {
    315   LIST_ENTRY                  *StorageLink;
    316   FORMSET_STORAGE             *Storage;
    317   EFI_STATUS                  Status;
    318 
    319   StorageLink = GetFirstNode (&FormSet->StorageListHead);
    320 
    321   while (!IsNull (&FormSet->StorageListHead, StorageLink)) {
    322     Storage = FORMSET_STORAGE_FROM_LINK(StorageLink);
    323 
    324     if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
    325       Status = GetBufferTypeDefaultIdAndStorageId (DefaultStore, Storage, FormSet, UefiDefaultsListHead);
    326       ASSERT_EFI_ERROR (Status);
    327     }
    328 
    329     StorageLink = GetNextNode (&FormSet->StorageListHead, StorageLink);
    330   }
    331 
    332   return EFI_SUCCESS;
    333 }
    334 
    335 
    336 /**
    337   Get the default value for Buffer Type storage from the FormSet in ThunkContext.
    338 
    339   The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE.
    340   They are inserted to the link list.
    341 
    342   @param  ThunkContext  Hii thunk context.
    343   @param  UefiDefaults  The head of link list for the output.
    344 
    345   @retval   EFI_SUCCESS          Successful.
    346 
    347 **/
    348 EFI_STATUS
    349 UefiIfrGetBufferTypeDefaults (
    350   IN  HII_THUNK_CONTEXT   *ThunkContext,
    351   OUT LIST_ENTRY          **UefiDefaults
    352   )
    353 {
    354   LIST_ENTRY            *DefaultLink;
    355   FORMSET_DEFAULTSTORE  *DefaultStore;
    356   EFI_STATUS            Status;
    357 
    358   ASSERT (UefiDefaults != NULL);
    359 
    360   *UefiDefaults = AllocateZeroPool (sizeof (LIST_ENTRY));
    361   ASSERT (*UefiDefaults != NULL);
    362   InitializeListHead (*UefiDefaults);
    363 
    364   DefaultLink = GetFirstNode (&ThunkContext->FormSet->DefaultStoreListHead);
    365   while (!IsNull (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink)) {
    366     DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
    367 
    368     Status = GetBufferTypeDefaultId (DefaultStore, ThunkContext->FormSet, *UefiDefaults);
    369     ASSERT_EFI_ERROR (Status);
    370 
    371     DefaultLink = GetNextNode (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink);
    372   }
    373 
    374   return EFI_SUCCESS;
    375 }
    376 
    377 
    378 /**
    379   Convert the UEFI Buffer Type default values to a Framework HII default
    380   values specified by a EFI_HII_VARIABLE_PACK_LIST structure.
    381 
    382   @param  ListHead             The link list of UEFI_IFR_BUFFER_STORAGE_NODE
    383                                which contains the default values retrived from a UEFI form set.
    384   @param  DefaultMask          The default mask.
    385                                The valid values are EFI_IFR_FLAG_DEFAULT and EFI_IFR_FLAG_MANUFACTURING.
    386                                UEFI spec only map EFI_IFR_FLAG_DEFAULT and EFI_IFR_FLAG_MANUFACTURING
    387                                from specification to valid default class.
    388   @param  UefiFormSetDefaultVarStoreId
    389                                ID of the default varstore in FormSet.
    390   @param  VariablePackList     The output default value in a format defined in Framework.
    391 
    392   @retval   EFI_SUCCESS                Successful.
    393   @retval   EFI_INVALID_PARAMETER      The default mask is not EFI_IFR_FLAG_DEFAULT or
    394                                        EFI_IFR_FLAG_MANUFACTURING.
    395 **/
    396 EFI_STATUS
    397 UefiDefaultsToFwDefaults (
    398   IN     LIST_ENTRY                  *ListHead,
    399   IN     UINTN                       DefaultMask,
    400   IN     EFI_VARSTORE_ID             UefiFormSetDefaultVarStoreId,
    401   OUT    EFI_HII_VARIABLE_PACK_LIST  **VariablePackList
    402   )
    403 {
    404   LIST_ENTRY                        *List;
    405   UEFI_IFR_BUFFER_STORAGE_NODE      *Node;
    406   UINTN                             Size;
    407   UINTN                             Count;
    408   UINT16                            DefaultId;
    409   EFI_HII_VARIABLE_PACK             *Pack;
    410   EFI_HII_VARIABLE_PACK_LIST        *PackList;
    411   UINTN                             Index;
    412 
    413   if (DefaultMask == EFI_IFR_FLAG_DEFAULT) {
    414     DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
    415   } else if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {
    416     DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
    417   } else {
    418     //
    419     // UEFI spec only map EFI_IFR_FLAG_DEFAULT and EFI_IFR_FLAG_MANUFACTURING
    420     // from specification to valid default class.
    421     //
    422     ASSERT (FALSE);
    423     return EFI_INVALID_PARAMETER;
    424   }
    425 
    426   //
    427   // Calculate the size of the output EFI_HII_VARIABLE_PACK_LIST structure
    428   //
    429   Size = 0;
    430   Count = 0;
    431   List = GetFirstNode (ListHead);
    432   while (!IsNull (ListHead, List)) {
    433     Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
    434 
    435     if (Node->DefaultId == DefaultId) {
    436       Size += Node->Size;
    437       Size += StrSize (Node->Name);
    438 
    439       Count++;
    440     }
    441 
    442     List = GetNextNode (ListHead, List);
    443   }
    444 
    445   if (Count == 0) {
    446     *VariablePackList = NULL;
    447     return EFI_NOT_FOUND;
    448   }
    449 
    450   Size = Size + Count * (sizeof (EFI_HII_VARIABLE_PACK_LIST) + sizeof (EFI_HII_VARIABLE_PACK));
    451 
    452   *VariablePackList = AllocateZeroPool (Size);
    453   ASSERT (*VariablePackList != NULL);
    454 
    455   List = GetFirstNode (ListHead);
    456 
    457   PackList = (EFI_HII_VARIABLE_PACK_LIST *) *VariablePackList;
    458   Pack     = (EFI_HII_VARIABLE_PACK *) (PackList + 1);
    459   Index = 0;
    460   while (!IsNull (ListHead, List)) {
    461     Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
    462 
    463     Size = 0;
    464     if (Node->DefaultId == DefaultId) {
    465       Size += Node->Size;
    466       Size += sizeof (EFI_HII_VARIABLE_PACK);
    467 
    468       Pack->VariableNameLength = (UINT32) StrSize (Node->Name);
    469 
    470       if (Node->StoreId == UefiFormSetDefaultVarStoreId) {
    471         //
    472         // The default VARSTORE in VFR from a Framework module has Varstore ID of 0.
    473         //
    474         Pack->VariableId = 0;
    475       } else {
    476         Pack->VariableId = Node->StoreId;
    477       }
    478 
    479       CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK), Node->Name, StrSize (Node->Name));
    480       Size += Pack->VariableNameLength;
    481 
    482       //
    483       // Initialize EFI_HII_VARIABLE_PACK
    484       //
    485       Pack->Header.Type   = 0;
    486       Pack->Header.Length = (UINT32) Size;
    487       CopyMem (&Pack->VariableGuid, &Node->Guid, sizeof (EFI_GUID));
    488 
    489       CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK) + Pack->VariableNameLength, Node->Buffer, Node->Size);
    490 
    491       Size += sizeof (EFI_HII_VARIABLE_PACK_LIST);
    492 
    493       //
    494       // Initialize EFI_HII_VARIABLE_PACK_LIST
    495       //
    496       PackList->VariablePack = Pack;
    497       Index++;
    498       if (Index < Count) {
    499         PackList->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *)((UINT8 *) PackList + Size);
    500 
    501         PackList = PackList->NextVariablePack;
    502         Pack     = (EFI_HII_VARIABLE_PACK *) (PackList + 1);
    503       }
    504 
    505     }
    506 
    507     List = GetNextNode (ListHead, List);
    508   }
    509 
    510 
    511   return EFI_SUCCESS;
    512 }
    513 
    514 
    515 /**
    516   Free up all buffer allocated for the link list of UEFI_IFR_BUFFER_STORAGE_NODE.
    517 
    518   @param  ListHead                  The link list of UEFI_IFR_BUFFER_STORAGE_NODE
    519                                     which contains the default values retrived from
    520                                     a UEFI form set.
    521 
    522 **/
    523 VOID
    524 FreeDefaultList (
    525   IN     LIST_ENTRY                  *ListHead
    526   )
    527 {
    528   LIST_ENTRY *Link;
    529   UEFI_IFR_BUFFER_STORAGE_NODE *Default;
    530 
    531   while (!IsListEmpty (ListHead)) {
    532     Link = GetFirstNode (ListHead);
    533 
    534     Default = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(Link);
    535 
    536     RemoveEntryList (Link);
    537 
    538     DestroyDefaultNode (Default);
    539   }
    540 
    541   FreePool (ListHead);
    542 }
    543 
    544