Home | History | Annotate | Download | only in DriverSampleDxe
      1 /** @file
      2 This is an example of how a driver might export data to the HII protocol to be
      3 later utilized by the Setup Protocol
      4 
      5 Copyright (c) 2004 - 2015, 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 
     17 #include "DriverSample.h"
     18 
     19 #define DISPLAY_ONLY_MY_ITEM  0x0002
     20 
     21 CHAR16     VariableName[] = L"MyIfrNVData";
     22 CHAR16     MyEfiVar[] = L"MyEfiVar";
     23 EFI_HANDLE                      DriverHandle[2] = {NULL, NULL};
     24 DRIVER_SAMPLE_PRIVATE_DATA      *mPrivateData = NULL;
     25 EFI_EVENT                       mEvent;
     26 
     27 HII_VENDOR_DEVICE_PATH  mHiiVendorDevicePath0 = {
     28   {
     29     {
     30       HARDWARE_DEVICE_PATH,
     31       HW_VENDOR_DP,
     32       {
     33         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     34         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     35       }
     36     },
     37     DRIVER_SAMPLE_FORMSET_GUID
     38   },
     39   {
     40     END_DEVICE_PATH_TYPE,
     41     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     42     {
     43       (UINT8) (END_DEVICE_PATH_LENGTH),
     44       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
     45     }
     46   }
     47 };
     48 
     49 HII_VENDOR_DEVICE_PATH  mHiiVendorDevicePath1 = {
     50   {
     51     {
     52       HARDWARE_DEVICE_PATH,
     53       HW_VENDOR_DP,
     54       {
     55         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     56         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     57       }
     58     },
     59     DRIVER_SAMPLE_INVENTORY_GUID
     60   },
     61   {
     62     END_DEVICE_PATH_TYPE,
     63     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     64     {
     65       (UINT8) (END_DEVICE_PATH_LENGTH),
     66       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
     67     }
     68   }
     69 };
     70 
     71 /**
     72   Add empty function for event process function.
     73 
     74   @param Event    The Event need to be process
     75   @param Context  The context of the event.
     76 
     77 **/
     78 VOID
     79 EFIAPI
     80 DriverSampleInternalEmptyFunction (
     81   IN  EFI_EVENT Event,
     82   IN  VOID      *Context
     83   )
     84 {
     85 }
     86 
     87 /**
     88   Notification function for keystrokes.
     89 
     90   @param[in] KeyData    The key that was pressed.
     91 
     92   @retval EFI_SUCCESS   The operation was successful.
     93 **/
     94 EFI_STATUS
     95 EFIAPI
     96 NotificationFunction(
     97   IN EFI_KEY_DATA *KeyData
     98   )
     99 {
    100   gBS->SignalEvent (mEvent);
    101 
    102   return EFI_SUCCESS;
    103 }
    104 
    105 /**
    106   Function to start monitoring for CTRL-C using SimpleTextInputEx.
    107 
    108   @retval EFI_SUCCESS           The feature is enabled.
    109   @retval EFI_OUT_OF_RESOURCES  There is not enough mnemory available.
    110 **/
    111 EFI_STATUS
    112 EFIAPI
    113 InternalStartMonitor(
    114   VOID
    115   )
    116 {
    117   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
    118   EFI_KEY_DATA                      KeyData;
    119   EFI_STATUS                        Status;
    120   EFI_HANDLE                        *Handles;
    121   UINTN                             HandleCount;
    122   UINTN                             HandleIndex;
    123   EFI_HANDLE                        NotifyHandle;
    124 
    125   Status = gBS->LocateHandleBuffer (
    126               ByProtocol,
    127               &gEfiSimpleTextInputExProtocolGuid,
    128               NULL,
    129               &HandleCount,
    130               &Handles
    131               );
    132   for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
    133     Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &SimpleEx);
    134     ASSERT_EFI_ERROR (Status);
    135 
    136     KeyData.KeyState.KeyToggleState = 0;
    137     KeyData.Key.ScanCode            = 0;
    138     KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
    139     KeyData.Key.UnicodeChar         = L'c';
    140 
    141     Status = SimpleEx->RegisterKeyNotify(
    142       SimpleEx,
    143       &KeyData,
    144       NotificationFunction,
    145       &NotifyHandle);
    146     if (EFI_ERROR (Status)) {
    147       break;
    148     }
    149 
    150     KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
    151     Status = SimpleEx->RegisterKeyNotify(
    152       SimpleEx,
    153       &KeyData,
    154       NotificationFunction,
    155       &NotifyHandle);
    156     if (EFI_ERROR (Status)) {
    157       break;
    158     }
    159   }
    160 
    161   return EFI_SUCCESS;
    162 }
    163 
    164 /**
    165   Function to stop monitoring for CTRL-C using SimpleTextInputEx.
    166 
    167   @retval EFI_SUCCESS           The feature is enabled.
    168   @retval EFI_OUT_OF_RESOURCES  There is not enough mnemory available.
    169 **/
    170 EFI_STATUS
    171 EFIAPI
    172 InternalStopMonitor(
    173   VOID
    174   )
    175 {
    176   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
    177   EFI_STATUS                        Status;
    178   EFI_HANDLE                        *Handles;
    179   EFI_KEY_DATA                      KeyData;
    180   UINTN                             HandleCount;
    181   UINTN                             HandleIndex;
    182   EFI_HANDLE                        NotifyHandle;
    183 
    184   Status = gBS->LocateHandleBuffer (
    185                 ByProtocol,
    186                 &gEfiSimpleTextInputExProtocolGuid,
    187                 NULL,
    188                 &HandleCount,
    189                 &Handles
    190                 );
    191   for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
    192     Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &SimpleEx);
    193     ASSERT_EFI_ERROR (Status);
    194 
    195     KeyData.KeyState.KeyToggleState = 0;
    196     KeyData.Key.ScanCode            = 0;
    197     KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
    198     KeyData.Key.UnicodeChar         = L'c';
    199 
    200     Status = SimpleEx->RegisterKeyNotify(
    201       SimpleEx,
    202       &KeyData,
    203       NotificationFunction,
    204       &NotifyHandle);
    205     if (!EFI_ERROR (Status)) {
    206       Status = SimpleEx->UnregisterKeyNotify (SimpleEx, NotifyHandle);
    207     }
    208 
    209     KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
    210     Status = SimpleEx->RegisterKeyNotify(
    211       SimpleEx,
    212       &KeyData,
    213       NotificationFunction,
    214       &NotifyHandle);
    215     if (!EFI_ERROR (Status)) {
    216       Status = SimpleEx->UnregisterKeyNotify (SimpleEx, NotifyHandle);
    217     }
    218   }
    219   return EFI_SUCCESS;
    220 }
    221 
    222 
    223 /**
    224   Encode the password using a simple algorithm.
    225 
    226   @param Password The string to be encoded.
    227   @param MaxSize  The size of the string.
    228 
    229 **/
    230 VOID
    231 EncodePassword (
    232   IN  CHAR16                      *Password,
    233   IN  UINTN                       MaxSize
    234   )
    235 {
    236   UINTN   Index;
    237   UINTN   Loop;
    238   CHAR16  *Buffer;
    239   CHAR16  *Key;
    240 
    241   Key     = L"MAR10648567";
    242   Buffer  = AllocateZeroPool (MaxSize);
    243   ASSERT (Buffer != NULL);
    244 
    245   for (Index = 0; Key[Index] != 0; Index++) {
    246     for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {
    247       Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);
    248     }
    249   }
    250 
    251   CopyMem (Password, Buffer, MaxSize);
    252 
    253   FreePool (Buffer);
    254   return ;
    255 }
    256 
    257 /**
    258   Validate the user's password.
    259 
    260   @param PrivateData This driver's private context data.
    261   @param StringId    The user's input.
    262 
    263   @retval EFI_SUCCESS   The user's input matches the password.
    264   @retval EFI_NOT_READY The user's input does not match the password.
    265 **/
    266 EFI_STATUS
    267 ValidatePassword (
    268   IN       DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData,
    269   IN       EFI_STRING_ID                   StringId
    270   )
    271 {
    272   EFI_STATUS                      Status;
    273   UINTN                           Index;
    274   UINTN                           BufferSize;
    275   UINTN                           PasswordMaxSize;
    276   CHAR16                          *Password;
    277   CHAR16                          *EncodedPassword;
    278   BOOLEAN                         OldPassword;
    279 
    280   //
    281   // Get encoded password first
    282   //
    283   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
    284   Status = gRT->GetVariable (
    285                   VariableName,
    286                   &gDriverSampleFormSetGuid,
    287                   NULL,
    288                   &BufferSize,
    289                   &PrivateData->Configuration
    290                   );
    291   if (EFI_ERROR (Status)) {
    292     //
    293     // Old password not exist, prompt for new password
    294     //
    295     return EFI_SUCCESS;
    296   }
    297 
    298   OldPassword = FALSE;
    299   PasswordMaxSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);
    300   //
    301   // Check whether we have any old password set
    302   //
    303   for (Index = 0; Index < PasswordMaxSize / sizeof (UINT16); Index++) {
    304     if (PrivateData->Configuration.WhatIsThePassword2[Index] != 0) {
    305       OldPassword = TRUE;
    306       break;
    307     }
    308   }
    309   if (!OldPassword) {
    310     //
    311     // Old password not exist, return EFI_SUCCESS to prompt for new password
    312     //
    313     return EFI_SUCCESS;
    314   }
    315 
    316   //
    317   // Get user input password
    318   //
    319   Password = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);
    320   if (Password == NULL) {
    321     return EFI_NOT_READY;
    322   }
    323   if (StrSize (Password) > PasswordMaxSize) {
    324     FreePool (Password);
    325     return EFI_NOT_READY;
    326   }
    327 
    328   //
    329   // Validate old password
    330   //
    331   EncodedPassword = AllocateZeroPool (PasswordMaxSize);
    332   ASSERT (EncodedPassword != NULL);
    333   StrnCpyS (EncodedPassword, PasswordMaxSize / sizeof (CHAR16), Password, StrLen (Password));
    334   EncodePassword (EncodedPassword, StrLen (EncodedPassword) * sizeof (CHAR16));
    335   if (CompareMem (EncodedPassword, PrivateData->Configuration.WhatIsThePassword2, PasswordMaxSize) != 0) {
    336     //
    337     // Old password mismatch, return EFI_NOT_READY to prompt for error message
    338     //
    339     Status = EFI_NOT_READY;
    340   } else {
    341     Status = EFI_SUCCESS;
    342   }
    343 
    344   FreePool (Password);
    345   FreePool (EncodedPassword);
    346 
    347   return Status;
    348 }
    349 
    350 /**
    351   Encode the password using a simple algorithm.
    352 
    353   @param PrivateData This driver's private context data.
    354   @param StringId    The password from User.
    355 
    356   @retval  EFI_SUCESS The operation is successful.
    357   @return  Other value if gRT->SetVariable () fails.
    358 
    359 **/
    360 EFI_STATUS
    361 SetPassword (
    362   IN DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData,
    363   IN EFI_STRING_ID                   StringId
    364   )
    365 {
    366   EFI_STATUS                      Status;
    367   CHAR16                          *Password;
    368   CHAR16                          *TempPassword;
    369   UINTN                           PasswordSize;
    370   DRIVER_SAMPLE_CONFIGURATION     *Configuration;
    371   UINTN                           BufferSize;
    372 
    373   //
    374   // Get Buffer Storage data from EFI variable
    375   //
    376   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
    377   Status = gRT->GetVariable (
    378                   VariableName,
    379                   &gDriverSampleFormSetGuid,
    380                   NULL,
    381                   &BufferSize,
    382                   &PrivateData->Configuration
    383                   );
    384   if (EFI_ERROR (Status)) {
    385     return Status;
    386   }
    387 
    388   //
    389   // Get user input password
    390   //
    391   Password = PrivateData->Configuration.WhatIsThePassword2;
    392   PasswordSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);
    393   ZeroMem (Password, PasswordSize);
    394 
    395   TempPassword = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);
    396   if (TempPassword == NULL) {
    397     return EFI_NOT_READY;
    398   }
    399   if (StrSize (TempPassword) > PasswordSize) {
    400     FreePool (TempPassword);
    401     return EFI_NOT_READY;
    402   }
    403   StrnCpyS (Password, PasswordSize / sizeof (CHAR16), TempPassword, StrLen (TempPassword));
    404   FreePool (TempPassword);
    405 
    406   //
    407   // Retrive uncommitted data from Browser
    408   //
    409   Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
    410   ASSERT (Configuration != NULL);
    411   if (HiiGetBrowserData (&gDriverSampleFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
    412     //
    413     // Update password's clear text in the screen
    414     //
    415     CopyMem (Configuration->PasswordClearText, Password, StrSize (Password));
    416 
    417     //
    418     // Update uncommitted data of Browser
    419     //
    420     HiiSetBrowserData (
    421        &gDriverSampleFormSetGuid,
    422        VariableName,
    423        sizeof (DRIVER_SAMPLE_CONFIGURATION),
    424        (UINT8 *) Configuration,
    425        NULL
    426        );
    427   }
    428 
    429   //
    430   // Free Configuration Buffer
    431   //
    432   FreePool (Configuration);
    433 
    434 
    435   //
    436   // Set password
    437   //
    438   EncodePassword (Password, StrLen (Password) * 2);
    439   Status = gRT->SetVariable(
    440                   VariableName,
    441                   &gDriverSampleFormSetGuid,
    442                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    443                   sizeof (DRIVER_SAMPLE_CONFIGURATION),
    444                   &PrivateData->Configuration
    445                   );
    446   return Status;
    447 }
    448 
    449 /**
    450  Update names of Name/Value storage to current language.
    451 
    452  @param PrivateData   Points to the driver private data.
    453 
    454  @retval EFI_SUCCESS   All names are successfully updated.
    455  @retval EFI_NOT_FOUND Failed to get Name from HII database.
    456 
    457 **/
    458 EFI_STATUS
    459 LoadNameValueNames (
    460   IN DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData
    461   )
    462 {
    463   UINTN      Index;
    464 
    465   //
    466   // Get Name/Value name string of current language
    467   //
    468   for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {
    469     PrivateData->NameValueName[Index] = HiiGetString (
    470                                          PrivateData->HiiHandle[0],
    471                                          PrivateData->NameStringId[Index],
    472                                          NULL
    473                                          );
    474     if (PrivateData->NameValueName[Index] == NULL) {
    475       return EFI_NOT_FOUND;
    476     }
    477   }
    478 
    479   return EFI_SUCCESS;
    480 }
    481 
    482 
    483 /**
    484   Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
    485   or WIDTH or VALUE.
    486   <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
    487 
    488   This is a internal function.
    489 
    490   @param  StringPtr              String in <BlockConfig> format and points to the
    491                                  first character of <Number>.
    492   @param  Number                 The output value. Caller takes the responsibility
    493                                  to free memory.
    494   @param  Len                    Length of the <Number>, in characters.
    495 
    496   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary
    497                                  structures.
    498   @retval EFI_SUCCESS            Value of <Number> is outputted in Number
    499                                  successfully.
    500 
    501 **/
    502 EFI_STATUS
    503 GetValueOfNumber (
    504   IN EFI_STRING                    StringPtr,
    505   OUT UINT8                        **Number,
    506   OUT UINTN                        *Len
    507   )
    508 {
    509   EFI_STRING               TmpPtr;
    510   UINTN                    Length;
    511   EFI_STRING               Str;
    512   UINT8                    *Buf;
    513   EFI_STATUS               Status;
    514   UINT8                    DigitUint8;
    515   UINTN                    Index;
    516   CHAR16                   TemStr[2];
    517 
    518   if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
    519     return EFI_INVALID_PARAMETER;
    520   }
    521 
    522   Buf = NULL;
    523 
    524   TmpPtr = StringPtr;
    525   while (*StringPtr != L'\0' && *StringPtr != L'&') {
    526     StringPtr++;
    527   }
    528   *Len   = StringPtr - TmpPtr;
    529   Length = *Len + 1;
    530 
    531   Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
    532   if (Str == NULL) {
    533     Status = EFI_OUT_OF_RESOURCES;
    534     goto Exit;
    535   }
    536   CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
    537   *(Str + *Len) = L'\0';
    538 
    539   Length = (Length + 1) / 2;
    540   Buf = (UINT8 *) AllocateZeroPool (Length);
    541   if (Buf == NULL) {
    542     Status = EFI_OUT_OF_RESOURCES;
    543     goto Exit;
    544   }
    545 
    546   Length = *Len;
    547   ZeroMem (TemStr, sizeof (TemStr));
    548   for (Index = 0; Index < Length; Index ++) {
    549     TemStr[0] = Str[Length - Index - 1];
    550     DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
    551     if ((Index & 1) == 0) {
    552       Buf [Index/2] = DigitUint8;
    553     } else {
    554       Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
    555     }
    556   }
    557 
    558   *Number = Buf;
    559   Status  = EFI_SUCCESS;
    560 
    561 Exit:
    562   if (Str != NULL) {
    563     FreePool (Str);
    564   }
    565 
    566   return Status;
    567 }
    568 
    569 /**
    570   Create altcfg string.
    571 
    572   @param  Result               The request result string.
    573   @param  ConfigHdr            The request head info. <ConfigHdr> format.
    574   @param  Offset               The offset of the parameter int he structure.
    575   @param  Width                The width of the parameter.
    576 
    577 
    578   @retval  The string with altcfg info append at the end.
    579 **/
    580 EFI_STRING
    581 CreateAltCfgString (
    582   IN     EFI_STRING     Result,
    583   IN     EFI_STRING     ConfigHdr,
    584   IN     UINTN          Offset,
    585   IN     UINTN          Width
    586   )
    587 {
    588   EFI_STRING StringPtr;
    589   EFI_STRING TmpStr;
    590   UINTN      NewLen;
    591 
    592   NewLen = StrLen (Result);
    593   //
    594   // String Len = ConfigResp + AltConfig + AltConfig + 1("\0")
    595   //
    596   NewLen = (NewLen + ((1 + StrLen (ConfigHdr) + 8 + 4) + (8 + 4 + 7 + 4 + 7 + 4)) * 2 + 1) * sizeof (CHAR16);
    597   StringPtr = AllocateZeroPool (NewLen);
    598   if (StringPtr == NULL) {
    599     return NULL;
    600   }
    601 
    602   TmpStr = StringPtr;
    603   if (Result != NULL) {
    604     StrCpyS (StringPtr, NewLen / sizeof (CHAR16), Result);
    605     StringPtr += StrLen (Result);
    606     FreePool (Result);
    607   }
    608 
    609   UnicodeSPrint (
    610   StringPtr,
    611   (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
    612   L"&%s&ALTCFG=%04x",
    613   ConfigHdr,
    614   EFI_HII_DEFAULT_CLASS_STANDARD
    615   );
    616   StringPtr += StrLen (StringPtr);
    617 
    618   UnicodeSPrint (
    619     StringPtr,
    620     (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
    621     L"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
    622     Offset,
    623     Width,
    624     DEFAULT_CLASS_STANDARD_VALUE
    625     );
    626   StringPtr += StrLen (StringPtr);
    627 
    628   UnicodeSPrint (
    629   StringPtr,
    630   (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
    631   L"&%s&ALTCFG=%04x",
    632   ConfigHdr,
    633   EFI_HII_DEFAULT_CLASS_MANUFACTURING
    634   );
    635   StringPtr += StrLen (StringPtr);
    636 
    637   UnicodeSPrint (
    638     StringPtr,
    639     (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
    640     L"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
    641     Offset,
    642     Width,
    643     DEFAULT_CLASS_MANUFACTURING_VALUE
    644     );
    645   StringPtr += StrLen (StringPtr);
    646 
    647   return TmpStr;
    648 }
    649 
    650 /**
    651   Check whether need to add the altcfg string. if need to add, add the altcfg
    652   string.
    653 
    654   @param  RequestResult              The request result string.
    655   @param  ConfigRequestHdr           The request head info. <ConfigHdr> format.
    656 
    657 **/
    658 VOID
    659 AppendAltCfgString (
    660   IN OUT EFI_STRING                       *RequestResult,
    661   IN     EFI_STRING                       ConfigRequestHdr
    662   )
    663 {
    664   EFI_STRING                          StringPtr;
    665   UINTN                               Length;
    666   UINT8                               *TmpBuffer;
    667   UINTN                               Offset;
    668   UINTN                               Width;
    669   UINTN                               BlockSize;
    670   UINTN                               ValueOffset;
    671   UINTN                               ValueWidth;
    672   EFI_STATUS                          Status;
    673 
    674   TmpBuffer = NULL;
    675   StringPtr = *RequestResult;
    676   StringPtr = StrStr (StringPtr, L"OFFSET");
    677   BlockSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
    678   ValueOffset = OFFSET_OF (DRIVER_SAMPLE_CONFIGURATION, GetDefaultValueFromAccess);
    679   ValueWidth  = sizeof (((DRIVER_SAMPLE_CONFIGURATION *)0)->GetDefaultValueFromAccess);
    680 
    681   if (StringPtr == NULL) {
    682     return;
    683   }
    684 
    685   while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
    686     StringPtr += StrLen (L"OFFSET=");
    687     //
    688     // Get Offset
    689     //
    690     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
    691     if (EFI_ERROR (Status)) {
    692       return;
    693     }
    694     Offset = 0;
    695     CopyMem (
    696      &Offset,
    697      TmpBuffer,
    698      (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
    699      );
    700     FreePool (TmpBuffer);
    701 
    702     StringPtr += Length;
    703     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
    704       return;
    705     }
    706     StringPtr += StrLen (L"&WIDTH=");
    707 
    708     //
    709     // Get Width
    710     //
    711     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
    712     if (EFI_ERROR (Status)) {
    713       return;
    714     }
    715     Width = 0;
    716     CopyMem (
    717      &Width,
    718      TmpBuffer,
    719      (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
    720      );
    721     FreePool (TmpBuffer);
    722 
    723     StringPtr += Length;
    724     if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
    725       return;
    726     }
    727     StringPtr += StrLen (L"&VALUE=");
    728 
    729     //
    730     // Get Value
    731     //
    732     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
    733     if (EFI_ERROR (Status)) {
    734       return;
    735     }
    736     StringPtr += Length;
    737 
    738     //
    739     // Calculate Value and convert it to hex string.
    740     //
    741     if (Offset + Width > BlockSize) {
    742       return;
    743     }
    744 
    745     if (Offset <= ValueOffset && Offset + Width >= ValueOffset + ValueWidth) {
    746       *RequestResult = CreateAltCfgString(*RequestResult, ConfigRequestHdr, ValueOffset, ValueWidth);
    747       return;
    748     }
    749   }
    750 }
    751 
    752 /**
    753   This function allows a caller to extract the current configuration for one
    754   or more named elements from the target driver.
    755 
    756   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
    757   @param  Request                A null-terminated Unicode string in
    758                                  <ConfigRequest> format.
    759   @param  Progress               On return, points to a character in the Request
    760                                  string. Points to the string's null terminator if
    761                                  request was successful. Points to the most recent
    762                                  '&' before the first failing name/value pair (or
    763                                  the beginning of the string if the failure is in
    764                                  the first name/value pair) if the request was not
    765                                  successful.
    766   @param  Results                A null-terminated Unicode string in
    767                                  <ConfigAltResp> format which has all values filled
    768                                  in for the names in the Request string. String to
    769                                  be allocated by the called function.
    770 
    771   @retval EFI_SUCCESS            The Results is filled with the requested values.
    772   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
    773   @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
    774   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
    775                                  driver.
    776 
    777 **/
    778 EFI_STATUS
    779 EFIAPI
    780 ExtractConfig (
    781   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
    782   IN  CONST EFI_STRING                       Request,
    783   OUT EFI_STRING                             *Progress,
    784   OUT EFI_STRING                             *Results
    785   )
    786 {
    787   EFI_STATUS                       Status;
    788   UINTN                            BufferSize;
    789   DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;
    790   EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;
    791   EFI_STRING                       ConfigRequest;
    792   EFI_STRING                       ConfigRequestHdr;
    793   UINTN                            Size;
    794   EFI_STRING                       Value;
    795   UINTN                            ValueStrLen;
    796   CHAR16                           BackupChar;
    797   CHAR16                           *StrPointer;
    798   BOOLEAN                          AllocatedRequest;
    799 
    800   if (Progress == NULL || Results == NULL) {
    801     return EFI_INVALID_PARAMETER;
    802   }
    803   //
    804   // Initialize the local variables.
    805   //
    806   ConfigRequestHdr  = NULL;
    807   ConfigRequest     = NULL;
    808   Size              = 0;
    809   *Progress         = Request;
    810   AllocatedRequest  = FALSE;
    811 
    812   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
    813   HiiConfigRouting = PrivateData->HiiConfigRouting;
    814 
    815   //
    816   // Get Buffer Storage data from EFI variable.
    817   // Try to get the current setting from variable.
    818   //
    819   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
    820   Status = gRT->GetVariable (
    821             VariableName,
    822             &gDriverSampleFormSetGuid,
    823             NULL,
    824             &BufferSize,
    825             &PrivateData->Configuration
    826             );
    827   if (EFI_ERROR (Status)) {
    828     return EFI_NOT_FOUND;
    829   }
    830 
    831   if (Request == NULL) {
    832     //
    833     // Request is set to NULL, construct full request string.
    834     //
    835 
    836     //
    837     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
    838     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
    839     //
    840     ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, PrivateData->DriverHandle[0]);
    841     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
    842     ConfigRequest = AllocateZeroPool (Size);
    843     ASSERT (ConfigRequest != NULL);
    844     AllocatedRequest = TRUE;
    845     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
    846     FreePool (ConfigRequestHdr);
    847     ConfigRequestHdr = NULL;
    848   } else {
    849     //
    850     // Check routing data in <ConfigHdr>.
    851     // Note: if only one Storage is used, then this checking could be skipped.
    852     //
    853     if (!HiiIsConfigHdrMatch (Request, &gDriverSampleFormSetGuid, NULL)) {
    854       return EFI_NOT_FOUND;
    855     }
    856     //
    857     // Check whether request for EFI Varstore. EFI varstore get data
    858     // through hii database, not support in this path.
    859     //
    860     if (HiiIsConfigHdrMatch(Request, &gDriverSampleFormSetGuid, MyEfiVar)) {
    861       return EFI_UNSUPPORTED;
    862     }
    863     //
    864     // Set Request to the unified request string.
    865     //
    866     ConfigRequest = Request;
    867     //
    868     // Check whether Request includes Request Element.
    869     //
    870     if (StrStr (Request, L"OFFSET") == NULL) {
    871       //
    872       // Check Request Element does exist in Reques String
    873       //
    874       StrPointer = StrStr (Request, L"PATH");
    875       if (StrPointer == NULL) {
    876         return EFI_INVALID_PARAMETER;
    877       }
    878       if (StrStr (StrPointer, L"&") == NULL) {
    879         Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);
    880         ConfigRequest    = AllocateZeroPool (Size);
    881         ASSERT (ConfigRequest != NULL);
    882         AllocatedRequest = TRUE;
    883         UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", Request, (UINT64)BufferSize);
    884       }
    885     }
    886   }
    887 
    888   //
    889   // Check if requesting Name/Value storage
    890   //
    891   if (StrStr (ConfigRequest, L"OFFSET") == NULL) {
    892     //
    893     // Update Name/Value storage Names
    894     //
    895     Status = LoadNameValueNames (PrivateData);
    896     if (EFI_ERROR (Status)) {
    897       return Status;
    898     }
    899 
    900     //
    901     // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"
    902     // <Request>   ::=<ConfigHdr>&Name0&Name1&Name2
    903     // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044
    904     //
    905     BufferSize = (StrLen (ConfigRequest) +
    906       1 + sizeof (PrivateData->Configuration.NameValueVar0) * 2 +
    907       1 + sizeof (PrivateData->Configuration.NameValueVar1) * 2 +
    908       1 + sizeof (PrivateData->Configuration.NameValueVar2) * 2 + 1) * sizeof (CHAR16);
    909     *Results = AllocateZeroPool (BufferSize);
    910     ASSERT (*Results != NULL);
    911     StrCpyS (*Results, BufferSize / sizeof (CHAR16), ConfigRequest);
    912     Value = *Results;
    913 
    914     //
    915     // Append value of NameValueVar0, type is UINT8
    916     //
    917     if ((Value = StrStr (*Results, PrivateData->NameValueName[0])) != NULL) {
    918       Value += StrLen (PrivateData->NameValueName[0]);
    919       ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar0) * 2) + 1);
    920       CopyMem (Value + ValueStrLen, Value, StrSize (Value));
    921 
    922       BackupChar = Value[ValueStrLen];
    923       *Value++   = L'=';
    924       Value += UnicodeValueToString (
    925                  Value,
    926                  PREFIX_ZERO | RADIX_HEX,
    927                  PrivateData->Configuration.NameValueVar0,
    928                  sizeof (PrivateData->Configuration.NameValueVar0) * 2
    929                  );
    930       *Value = BackupChar;
    931     }
    932 
    933     //
    934     // Append value of NameValueVar1, type is UINT16
    935     //
    936     if ((Value = StrStr (*Results, PrivateData->NameValueName[1])) != NULL) {
    937       Value += StrLen (PrivateData->NameValueName[1]);
    938       ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar1) * 2) + 1);
    939       CopyMem (Value + ValueStrLen, Value, StrSize (Value));
    940 
    941       BackupChar = Value[ValueStrLen];
    942       *Value++   = L'=';
    943       Value += UnicodeValueToString (
    944                 Value,
    945                 PREFIX_ZERO | RADIX_HEX,
    946                 PrivateData->Configuration.NameValueVar1,
    947                 sizeof (PrivateData->Configuration.NameValueVar1) * 2
    948                 );
    949       *Value = BackupChar;
    950     }
    951 
    952     //
    953     // Append value of NameValueVar2, type is CHAR16 *
    954     //
    955     if ((Value = StrStr (*Results, PrivateData->NameValueName[2])) != NULL) {
    956       Value += StrLen (PrivateData->NameValueName[2]);
    957       ValueStrLen = StrLen (PrivateData->Configuration.NameValueVar2) * 4 + 1;
    958       CopyMem (Value + ValueStrLen, Value, StrSize (Value));
    959 
    960       *Value++ = L'=';
    961       //
    962       // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
    963       //
    964       StrPointer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;
    965       for (; *StrPointer != L'\0'; StrPointer++) {
    966         Value += UnicodeValueToString (Value, PREFIX_ZERO | RADIX_HEX, *StrPointer, 4);
    967       }
    968     }
    969 
    970     Status = EFI_SUCCESS;
    971   } else {
    972     //
    973     // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
    974     //
    975     Status = HiiConfigRouting->BlockToConfig (
    976                                   HiiConfigRouting,
    977                                   ConfigRequest,
    978                                   (UINT8 *) &PrivateData->Configuration,
    979                                   BufferSize,
    980                                   Results,
    981                                   Progress
    982                                   );
    983     if (!EFI_ERROR (Status)) {
    984       ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, PrivateData->DriverHandle[0]);
    985       AppendAltCfgString(Results, ConfigRequestHdr);
    986     }
    987   }
    988 
    989   //
    990   // Free the allocated config request string.
    991   //
    992   if (AllocatedRequest) {
    993     FreePool (ConfigRequest);
    994   }
    995 
    996   if (ConfigRequestHdr != NULL) {
    997     FreePool (ConfigRequestHdr);
    998   }
    999   //
   1000   // Set Progress string to the original request string.
   1001   //
   1002   if (Request == NULL) {
   1003     *Progress = NULL;
   1004   } else if (StrStr (Request, L"OFFSET") == NULL) {
   1005     *Progress = Request + StrLen (Request);
   1006   }
   1007 
   1008   return Status;
   1009 }
   1010 
   1011 
   1012 /**
   1013   This function processes the results of changes in configuration.
   1014 
   1015   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   1016   @param  Configuration          A null-terminated Unicode string in <ConfigResp>
   1017                                  format.
   1018   @param  Progress               A pointer to a string filled in with the offset of
   1019                                  the most recent '&' before the first failing
   1020                                  name/value pair (or the beginning of the string if
   1021                                  the failure is in the first name/value pair) or
   1022                                  the terminating NULL if all was successful.
   1023 
   1024   @retval EFI_SUCCESS            The Results is processed successfully.
   1025   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
   1026   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
   1027                                  driver.
   1028 
   1029 **/
   1030 EFI_STATUS
   1031 EFIAPI
   1032 RouteConfig (
   1033   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
   1034   IN  CONST EFI_STRING                       Configuration,
   1035   OUT EFI_STRING                             *Progress
   1036   )
   1037 {
   1038   EFI_STATUS                       Status;
   1039   UINTN                            BufferSize;
   1040   DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;
   1041   EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;
   1042   CHAR16                           *Value;
   1043   CHAR16                           *StrPtr;
   1044   CHAR16                           TemStr[5];
   1045   UINT8                            *DataBuffer;
   1046   UINT8                            DigitUint8;
   1047   UINTN                            Index;
   1048   CHAR16                           *StrBuffer;
   1049 
   1050   if (Configuration == NULL || Progress == NULL) {
   1051     return EFI_INVALID_PARAMETER;
   1052   }
   1053 
   1054   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
   1055   HiiConfigRouting = PrivateData->HiiConfigRouting;
   1056   *Progress = Configuration;
   1057 
   1058   //
   1059   // Check routing data in <ConfigHdr>.
   1060   // Note: if only one Storage is used, then this checking could be skipped.
   1061   //
   1062   if (!HiiIsConfigHdrMatch (Configuration, &gDriverSampleFormSetGuid, NULL)) {
   1063     return EFI_NOT_FOUND;
   1064   }
   1065 
   1066   //
   1067   // Check whether request for EFI Varstore. EFI varstore get data
   1068   // through hii database, not support in this path.
   1069   //
   1070   if (HiiIsConfigHdrMatch(Configuration, &gDriverSampleFormSetGuid, MyEfiVar)) {
   1071     return EFI_UNSUPPORTED;
   1072   }
   1073 
   1074   //
   1075   // Get Buffer Storage data from EFI variable
   1076   //
   1077   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
   1078   Status = gRT->GetVariable (
   1079             VariableName,
   1080             &gDriverSampleFormSetGuid,
   1081             NULL,
   1082             &BufferSize,
   1083             &PrivateData->Configuration
   1084             );
   1085   if (EFI_ERROR (Status)) {
   1086     return Status;
   1087   }
   1088 
   1089   //
   1090   // Check if configuring Name/Value storage
   1091   //
   1092   if (StrStr (Configuration, L"OFFSET") == NULL) {
   1093     //
   1094     // Update Name/Value storage Names
   1095     //
   1096     Status = LoadNameValueNames (PrivateData);
   1097     if (EFI_ERROR (Status)) {
   1098       return Status;
   1099     }
   1100 
   1101     //
   1102     // Convert value for NameValueVar0
   1103     //
   1104     if ((Value = StrStr (Configuration, PrivateData->NameValueName[0])) != NULL) {
   1105       //
   1106       // Skip "Name="
   1107       //
   1108       Value += StrLen (PrivateData->NameValueName[0]);
   1109       Value++;
   1110       //
   1111       // Get Value String
   1112       //
   1113       StrPtr = StrStr (Value, L"&");
   1114       if (StrPtr == NULL) {
   1115         StrPtr = Value + StrLen (Value);
   1116       }
   1117       //
   1118       // Convert Value to Buffer data
   1119       //
   1120       DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar0;
   1121       ZeroMem (TemStr, sizeof (TemStr));
   1122       for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {
   1123         TemStr[0] = *StrPtr;
   1124         DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
   1125         if ((Index & 1) == 0) {
   1126           DataBuffer [Index/2] = DigitUint8;
   1127         } else {
   1128           DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);
   1129         }
   1130       }
   1131     }
   1132 
   1133     //
   1134     // Convert value for NameValueVar1
   1135     //
   1136     if ((Value = StrStr (Configuration, PrivateData->NameValueName[1])) != NULL) {
   1137       //
   1138       // Skip "Name="
   1139       //
   1140       Value += StrLen (PrivateData->NameValueName[1]);
   1141       Value++;
   1142       //
   1143       // Get Value String
   1144       //
   1145       StrPtr = StrStr (Value, L"&");
   1146       if (StrPtr == NULL) {
   1147         StrPtr = Value + StrLen (Value);
   1148       }
   1149       //
   1150       // Convert Value to Buffer data
   1151       //
   1152       DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar1;
   1153       ZeroMem (TemStr, sizeof (TemStr));
   1154       for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {
   1155         TemStr[0] = *StrPtr;
   1156         DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
   1157         if ((Index & 1) == 0) {
   1158           DataBuffer [Index/2] = DigitUint8;
   1159         } else {
   1160           DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);
   1161         }
   1162       }
   1163     }
   1164 
   1165     //
   1166     // Convert value for NameValueVar2
   1167     //
   1168     if ((Value = StrStr (Configuration, PrivateData->NameValueName[2])) != NULL) {
   1169       //
   1170       // Skip "Name="
   1171       //
   1172       Value += StrLen (PrivateData->NameValueName[2]);
   1173       Value++;
   1174       //
   1175       // Get Value String
   1176       //
   1177       StrPtr = StrStr (Value, L"&");
   1178       if (StrPtr == NULL) {
   1179         StrPtr = Value + StrLen (Value);
   1180       }
   1181       //
   1182       // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
   1183       //
   1184       StrBuffer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;
   1185       ZeroMem (TemStr, sizeof (TemStr));
   1186       while (Value < StrPtr) {
   1187         StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value, 4);
   1188         *(StrBuffer++) = (CHAR16) StrHexToUint64 (TemStr);
   1189         Value += 4;
   1190       }
   1191       *StrBuffer = L'\0';
   1192     }
   1193 
   1194     //
   1195     // Store Buffer Storage back to EFI variable
   1196     //
   1197     Status = gRT->SetVariable(
   1198       VariableName,
   1199       &gDriverSampleFormSetGuid,
   1200       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
   1201       sizeof (DRIVER_SAMPLE_CONFIGURATION),
   1202       &PrivateData->Configuration
   1203       );
   1204 
   1205     return Status;
   1206   }
   1207 
   1208   //
   1209   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
   1210   //
   1211   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
   1212   Status = HiiConfigRouting->ConfigToBlock (
   1213                                HiiConfigRouting,
   1214                                Configuration,
   1215                                (UINT8 *) &PrivateData->Configuration,
   1216                                &BufferSize,
   1217                                Progress
   1218                                );
   1219   if (EFI_ERROR (Status)) {
   1220     return Status;
   1221   }
   1222 
   1223   //
   1224   // Store Buffer Storage back to EFI variable
   1225   //
   1226   Status = gRT->SetVariable(
   1227                   VariableName,
   1228                   &gDriverSampleFormSetGuid,
   1229                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
   1230                   sizeof (DRIVER_SAMPLE_CONFIGURATION),
   1231                   &PrivateData->Configuration
   1232                   );
   1233 
   1234   return Status;
   1235 }
   1236 
   1237 
   1238 /**
   1239   This function processes the results of changes in configuration.
   1240 
   1241   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   1242   @param  Action                 Specifies the type of action taken by the browser.
   1243   @param  QuestionId             A unique value which is sent to the original
   1244                                  exporting driver so that it can identify the type
   1245                                  of data to expect.
   1246   @param  Type                   The type of value for the question.
   1247   @param  Value                  A pointer to the data being sent to the original
   1248                                  exporting driver.
   1249   @param  ActionRequest          On return, points to the action requested by the
   1250                                  callback function.
   1251 
   1252   @retval EFI_SUCCESS            The callback successfully handled the action.
   1253   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
   1254                                  variable and its data.
   1255   @retval EFI_DEVICE_ERROR       The variable could not be saved.
   1256   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
   1257                                  callback.
   1258 
   1259 **/
   1260 EFI_STATUS
   1261 EFIAPI
   1262 DriverCallback (
   1263   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
   1264   IN  EFI_BROWSER_ACTION                     Action,
   1265   IN  EFI_QUESTION_ID                        QuestionId,
   1266   IN  UINT8                                  Type,
   1267   IN  EFI_IFR_TYPE_VALUE                     *Value,
   1268   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
   1269   )
   1270 {
   1271   DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData;
   1272   EFI_STATUS                      Status;
   1273   VOID                            *StartOpCodeHandle;
   1274   VOID                            *OptionsOpCodeHandle;
   1275   EFI_IFR_GUID_LABEL              *StartLabel;
   1276   VOID                            *EndOpCodeHandle;
   1277   EFI_IFR_GUID_LABEL              *EndLabel;
   1278   EFI_INPUT_KEY                   Key;
   1279   DRIVER_SAMPLE_CONFIGURATION     *Configuration;
   1280   MY_EFI_VARSTORE_DATA            *EfiData;
   1281   EFI_FORM_ID                     FormId;
   1282   EFI_STRING                      Progress;
   1283   EFI_STRING                      Results;
   1284   UINT32                          ProgressErr;
   1285   CHAR16                          *TmpStr;
   1286 
   1287   if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))||
   1288     (ActionRequest == NULL)) {
   1289     return EFI_INVALID_PARAMETER;
   1290   }
   1291 
   1292 
   1293   FormId = 0;
   1294   ProgressErr = 0;
   1295   Status = EFI_SUCCESS;
   1296   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
   1297 
   1298   switch (Action) {
   1299   case EFI_BROWSER_ACTION_FORM_OPEN:
   1300     {
   1301       if (QuestionId == 0x1234) {
   1302         //
   1303         // Sample CallBack for UEFI FORM_OPEN action:
   1304         //   Add Save action into Form 3 when Form 1 is opened.
   1305         //   This will be done only in FORM_OPEN CallBack of question with ID 0x1234 from Form 1.
   1306         //
   1307         PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
   1308 
   1309         //
   1310         // Initialize the container for dynamic opcodes
   1311         //
   1312         StartOpCodeHandle = HiiAllocateOpCodeHandle ();
   1313         ASSERT (StartOpCodeHandle != NULL);
   1314 
   1315         //
   1316         // Create Hii Extend Label OpCode as the start opcode
   1317         //
   1318         StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
   1319         StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   1320         StartLabel->Number       = LABEL_UPDATE2;
   1321 
   1322         HiiCreateActionOpCode (
   1323           StartOpCodeHandle,                // Container for dynamic created opcodes
   1324           0x1238,                           // Question ID
   1325           STRING_TOKEN(STR_SAVE_TEXT),      // Prompt text
   1326           STRING_TOKEN(STR_SAVE_TEXT),      // Help text
   1327           EFI_IFR_FLAG_CALLBACK,            // Question flag
   1328           0                                 // Action String ID
   1329         );
   1330 
   1331         HiiUpdateForm (
   1332           PrivateData->HiiHandle[0],  // HII handle
   1333           &gDriverSampleFormSetGuid,  // Formset GUID
   1334           0x3,                        // Form ID
   1335           StartOpCodeHandle,          // Label for where to insert opcodes
   1336           NULL                        // Insert data
   1337           );
   1338 
   1339         HiiFreeOpCodeHandle (StartOpCodeHandle);
   1340       }
   1341 
   1342       if (QuestionId == 0x1247) {
   1343         Status = InternalStartMonitor ();
   1344         ASSERT_EFI_ERROR (Status);
   1345       }
   1346     }
   1347     break;
   1348 
   1349   case EFI_BROWSER_ACTION_FORM_CLOSE:
   1350     {
   1351       if (QuestionId == 0x5678) {
   1352         //
   1353         // Sample CallBack for UEFI FORM_CLOSE action:
   1354         //   Show up a pop-up to specify Form 3 will be closed when exit Form 3.
   1355         //
   1356         do {
   1357           CreatePopUp (
   1358             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   1359             &Key,
   1360             L"",
   1361             L"You are going to leave third Form!",
   1362             L"Press ESC or ENTER to continue ...",
   1363             L"",
   1364             NULL
   1365             );
   1366         } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
   1367       }
   1368 
   1369       if (QuestionId == 0x1247) {
   1370         Status = InternalStopMonitor ();
   1371         ASSERT_EFI_ERROR (Status);
   1372       }
   1373     }
   1374     break;
   1375 
   1376   case EFI_BROWSER_ACTION_RETRIEVE:
   1377     {
   1378       switch (QuestionId ) {
   1379       case 0x1248:
   1380         if (Type != EFI_IFR_TYPE_REF) {
   1381           return EFI_INVALID_PARAMETER;
   1382         }
   1383         Value->ref.FormId = 0x3;
   1384         break;
   1385 
   1386       case 0x5678:
   1387       case 0x1247:
   1388         //
   1389         // We will reach here once the Question is refreshed
   1390         //
   1391 
   1392         //
   1393         // Initialize the container for dynamic opcodes
   1394         //
   1395         StartOpCodeHandle = HiiAllocateOpCodeHandle ();
   1396         ASSERT (StartOpCodeHandle != NULL);
   1397 
   1398         //
   1399         // Create Hii Extend Label OpCode as the start opcode
   1400         //
   1401         StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
   1402         StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   1403         if (QuestionId == 0x5678) {
   1404           StartLabel->Number       = LABEL_UPDATE2;
   1405           FormId                   = 0x03;
   1406           PrivateData->Configuration.DynamicRefresh++;
   1407         } else if (QuestionId == 0x1247 ) {
   1408           StartLabel->Number       = LABEL_UPDATE3;
   1409           FormId                   = 0x06;
   1410           PrivateData->Configuration.RefreshGuidCount++;
   1411         }
   1412 
   1413         HiiCreateActionOpCode (
   1414           StartOpCodeHandle,                // Container for dynamic created opcodes
   1415           0x1237,                           // Question ID
   1416           STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text
   1417           STRING_TOKEN(STR_EXIT_TEXT),      // Help text
   1418           EFI_IFR_FLAG_CALLBACK,            // Question flag
   1419           0                                 // Action String ID
   1420         );
   1421 
   1422         HiiUpdateForm (
   1423           PrivateData->HiiHandle[0],        // HII handle
   1424           &gDriverSampleFormSetGuid,        // Formset GUID
   1425           FormId,                           // Form ID
   1426           StartOpCodeHandle,                // Label for where to insert opcodes
   1427           NULL                              // Insert data
   1428         );
   1429 
   1430         HiiFreeOpCodeHandle (StartOpCodeHandle);
   1431 
   1432         //
   1433         // Refresh the Question value
   1434         //
   1435         Status = gRT->SetVariable(
   1436                         VariableName,
   1437                         &gDriverSampleFormSetGuid,
   1438                         EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
   1439                         sizeof (DRIVER_SAMPLE_CONFIGURATION),
   1440                         &PrivateData->Configuration
   1441                         );
   1442 
   1443         if (QuestionId == 0x5678) {
   1444           //
   1445           // Update uncommitted data of Browser
   1446           //
   1447           EfiData = AllocateZeroPool (sizeof (MY_EFI_VARSTORE_DATA));
   1448           ASSERT (EfiData != NULL);
   1449           if (HiiGetBrowserData (&gDriverSampleFormSetGuid, MyEfiVar, sizeof (MY_EFI_VARSTORE_DATA), (UINT8 *) EfiData)) {
   1450             EfiData->Field8 = 111;
   1451             HiiSetBrowserData (
   1452               &gDriverSampleFormSetGuid,
   1453               MyEfiVar,
   1454               sizeof (MY_EFI_VARSTORE_DATA),
   1455               (UINT8 *) EfiData,
   1456               NULL
   1457             );
   1458           }
   1459           FreePool (EfiData);
   1460         }
   1461         break;
   1462       }
   1463     }
   1464     break;
   1465 
   1466   case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
   1467     {
   1468       switch (QuestionId) {
   1469       case 0x1240:
   1470         Value->u8 = DEFAULT_CLASS_STANDARD_VALUE;
   1471       break;
   1472 
   1473       default:
   1474         Status = EFI_UNSUPPORTED;
   1475       break;
   1476       }
   1477     }
   1478     break;
   1479 
   1480   case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
   1481     {
   1482       switch (QuestionId) {
   1483       case 0x1240:
   1484         Value->u8 = DEFAULT_CLASS_MANUFACTURING_VALUE;
   1485       break;
   1486 
   1487       default:
   1488         Status = EFI_UNSUPPORTED;
   1489       break;
   1490       }
   1491     }
   1492     break;
   1493 
   1494   case EFI_BROWSER_ACTION_CHANGING:
   1495   {
   1496     switch (QuestionId) {
   1497     case 0x1249:
   1498       {
   1499         if (Type != EFI_IFR_TYPE_REF) {
   1500           return EFI_INVALID_PARAMETER;
   1501         }
   1502 
   1503         Value->ref.FormId = 0x1234;
   1504       }
   1505     break;
   1506     case 0x1234:
   1507       //
   1508       // Initialize the container for dynamic opcodes
   1509       //
   1510       StartOpCodeHandle = HiiAllocateOpCodeHandle ();
   1511       ASSERT (StartOpCodeHandle != NULL);
   1512 
   1513       EndOpCodeHandle = HiiAllocateOpCodeHandle ();
   1514       ASSERT (EndOpCodeHandle != NULL);
   1515 
   1516       //
   1517       // Create Hii Extend Label OpCode as the start opcode
   1518       //
   1519       StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
   1520       StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   1521       StartLabel->Number       = LABEL_UPDATE1;
   1522 
   1523       //
   1524       // Create Hii Extend Label OpCode as the end opcode
   1525       //
   1526       EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
   1527       EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   1528       EndLabel->Number       = LABEL_END;
   1529 
   1530       HiiCreateActionOpCode (
   1531         StartOpCodeHandle,                // Container for dynamic created opcodes
   1532         0x1237,                           // Question ID
   1533         STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text
   1534         STRING_TOKEN(STR_EXIT_TEXT),      // Help text
   1535         EFI_IFR_FLAG_CALLBACK,            // Question flag
   1536         0                                 // Action String ID
   1537       );
   1538 
   1539       //
   1540       // Create Option OpCode
   1541       //
   1542       OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
   1543       ASSERT (OptionsOpCodeHandle != NULL);
   1544 
   1545       HiiCreateOneOfOptionOpCode (
   1546         OptionsOpCodeHandle,
   1547         STRING_TOKEN (STR_BOOT_OPTION1),
   1548         0,
   1549         EFI_IFR_NUMERIC_SIZE_1,
   1550         1
   1551         );
   1552 
   1553       HiiCreateOneOfOptionOpCode (
   1554         OptionsOpCodeHandle,
   1555         STRING_TOKEN (STR_BOOT_OPTION2),
   1556         0,
   1557         EFI_IFR_NUMERIC_SIZE_1,
   1558         2
   1559         );
   1560 
   1561       //
   1562       // Prepare initial value for the dynamic created oneof Question
   1563       //
   1564       PrivateData->Configuration.DynamicOneof = 2;
   1565       Status = gRT->SetVariable(
   1566                       VariableName,
   1567                       &gDriverSampleFormSetGuid,
   1568                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
   1569                       sizeof (DRIVER_SAMPLE_CONFIGURATION),
   1570                       &PrivateData->Configuration
   1571                       );
   1572 
   1573       //
   1574       // Set initial vlaue of dynamic created oneof Question in Form Browser
   1575       //
   1576       Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
   1577       ASSERT (Configuration != NULL);
   1578       if (HiiGetBrowserData (&gDriverSampleFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
   1579         Configuration->DynamicOneof = 2;
   1580 
   1581         //
   1582         // Update uncommitted data of Browser
   1583         //
   1584         HiiSetBrowserData (
   1585           &gDriverSampleFormSetGuid,
   1586           VariableName,
   1587           sizeof (DRIVER_SAMPLE_CONFIGURATION),
   1588           (UINT8 *) Configuration,
   1589           NULL
   1590           );
   1591       }
   1592       FreePool (Configuration);
   1593 
   1594       HiiCreateOneOfOpCode (
   1595         StartOpCodeHandle,                         // Container for dynamic created opcodes
   1596         0x8001,                                    // Question ID (or call it "key")
   1597         CONFIGURATION_VARSTORE_ID,                 // VarStore ID
   1598         (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET,        // Offset in Buffer Storage
   1599         STRING_TOKEN (STR_ONE_OF_PROMPT),          // Question prompt text
   1600         STRING_TOKEN (STR_ONE_OF_HELP),            // Question help text
   1601         EFI_IFR_FLAG_CALLBACK,                     // Question flag
   1602         EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question Value
   1603         OptionsOpCodeHandle,                       // Option Opcode list
   1604         NULL                                       // Default Opcode is NULl
   1605         );
   1606 
   1607       HiiCreateOrderedListOpCode (
   1608         StartOpCodeHandle,                         // Container for dynamic created opcodes
   1609         0x8002,                                    // Question ID
   1610         CONFIGURATION_VARSTORE_ID,                 // VarStore ID
   1611         (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET,  // Offset in Buffer Storage
   1612         STRING_TOKEN (STR_BOOT_OPTIONS),           // Question prompt text
   1613         STRING_TOKEN (STR_BOOT_OPTIONS),           // Question help text
   1614         EFI_IFR_FLAG_RESET_REQUIRED,               // Question flag
   1615         0,                                         // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
   1616         EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question value
   1617         5,                                         // Maximum container
   1618         OptionsOpCodeHandle,                       // Option Opcode list
   1619         NULL                                       // Default Opcode is NULl
   1620         );
   1621 
   1622       HiiCreateTextOpCode (
   1623         StartOpCodeHandle,
   1624         STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
   1625         STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
   1626         STRING_TOKEN(STR_TEXT_SAMPLE_STRING)
   1627       );
   1628 
   1629       HiiCreateDateOpCode (
   1630         StartOpCodeHandle,
   1631         0x8004,
   1632         0x0,
   1633         0x0,
   1634         STRING_TOKEN(STR_DATE_SAMPLE_HELP),
   1635         STRING_TOKEN(STR_DATE_SAMPLE_HELP),
   1636         0,
   1637         QF_DATE_STORAGE_TIME,
   1638         NULL
   1639         );
   1640 
   1641       HiiCreateTimeOpCode (
   1642         StartOpCodeHandle,
   1643         0x8005,
   1644         0x0,
   1645         0x0,
   1646         STRING_TOKEN(STR_TIME_SAMPLE_HELP),
   1647         STRING_TOKEN(STR_TIME_SAMPLE_HELP),
   1648         0,
   1649         QF_TIME_STORAGE_TIME,
   1650         NULL
   1651         );
   1652 
   1653       HiiCreateGotoOpCode (
   1654         StartOpCodeHandle,                // Container for dynamic created opcodes
   1655         1,                                // Target Form ID
   1656         STRING_TOKEN (STR_GOTO_FORM1),    // Prompt text
   1657         STRING_TOKEN (STR_GOTO_HELP),     // Help text
   1658         0,                                // Question flag
   1659         0x8003                            // Question ID
   1660         );
   1661 
   1662       HiiUpdateForm (
   1663         PrivateData->HiiHandle[0],  // HII handle
   1664         &gDriverSampleFormSetGuid,  // Formset GUID
   1665         0x1234,                     // Form ID
   1666         StartOpCodeHandle,          // Label for where to insert opcodes
   1667         EndOpCodeHandle             // Replace data
   1668         );
   1669 
   1670       HiiFreeOpCodeHandle (StartOpCodeHandle);
   1671       HiiFreeOpCodeHandle (OptionsOpCodeHandle);
   1672       HiiFreeOpCodeHandle (EndOpCodeHandle);
   1673       break;
   1674 
   1675     case 0x2000:
   1676       //
   1677       // Only used to update the state.
   1678       //
   1679       if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0) &&
   1680         (PrivateData->PasswordState == BROWSER_STATE_SET_PASSWORD)) {
   1681         PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
   1682         return EFI_INVALID_PARAMETER;
   1683       }
   1684 
   1685       //
   1686       // When try to set a new password, user will be chanlleged with old password.
   1687       // The Callback is responsible for validating old password input by user,
   1688       // If Callback return EFI_SUCCESS, it indicates validation pass.
   1689       //
   1690       switch (PrivateData->PasswordState) {
   1691       case BROWSER_STATE_VALIDATE_PASSWORD:
   1692         Status = ValidatePassword (PrivateData, Value->string);
   1693         if (Status == EFI_SUCCESS) {
   1694           PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
   1695         }
   1696         break;
   1697 
   1698       case BROWSER_STATE_SET_PASSWORD:
   1699         Status = SetPassword (PrivateData, Value->string);
   1700         PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
   1701         break;
   1702 
   1703       default:
   1704         break;
   1705       }
   1706 
   1707       break;
   1708 
   1709     default:
   1710       break;
   1711     }
   1712   }
   1713   break;
   1714 
   1715   case EFI_BROWSER_ACTION_CHANGED:
   1716     switch (QuestionId) {
   1717       case 0x1237:
   1718         //
   1719         // User press "Exit now", request Browser to exit
   1720         //
   1721         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
   1722         break;
   1723 
   1724       case 0x1238:
   1725         //
   1726         // User press "Save now", request Browser to save the uncommitted data.
   1727         //
   1728         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
   1729         break;
   1730 
   1731       case 0x1241:
   1732       case 0x1246:
   1733         //
   1734         // User press "Submit current form and Exit now", request Browser to submit current form and exit
   1735         //
   1736         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
   1737         break;
   1738 
   1739       case 0x1242:
   1740         //
   1741         // User press "Discard current form now", request Browser to discard the uncommitted data.
   1742         //
   1743         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD;
   1744         break;
   1745 
   1746       case 0x1243:
   1747         //
   1748         // User press "Submit current form now", request Browser to save the uncommitted data.
   1749         //
   1750         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
   1751         break;
   1752 
   1753       case 0x1244:
   1754       case 0x1245:
   1755         //
   1756         // User press "Discard current form and Exit now", request Browser to discard the uncommitted data and exit.
   1757         //
   1758         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
   1759         break;
   1760 
   1761       case 0x1231:
   1762         //
   1763         // 1. Check to see whether system support keyword.
   1764         //
   1765         Status = PrivateData->HiiKeywordHandler->GetData (PrivateData->HiiKeywordHandler,
   1766                                                           L"NAMESPACE=x-UEFI-ns",
   1767                                                           L"KEYWORD=iSCSIBootEnable",
   1768                                                           &Progress,
   1769                                                           &ProgressErr,
   1770                                                           &Results
   1771                                                          );
   1772         if (EFI_ERROR (Status)) {
   1773           do {
   1774             CreatePopUp (
   1775               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   1776               &Key,
   1777               L"",
   1778               L"This system not support this keyword!",
   1779               L"Press ENTER to continue ...",
   1780               L"",
   1781               NULL
   1782               );
   1783           } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
   1784 
   1785           Status = EFI_SUCCESS;
   1786           break;
   1787         }
   1788 
   1789         //
   1790         // 2. If system support this keyword, just try to change value.
   1791         //
   1792 
   1793         //
   1794         // Change value from '0' to '1' or from '1' to '0'
   1795         //
   1796         TmpStr = StrStr (Results, L"&VALUE=");
   1797         ASSERT (TmpStr != NULL);
   1798         TmpStr += StrLen (L"&VALUE=");
   1799         TmpStr++;
   1800         if (*TmpStr == L'0') {
   1801           *TmpStr = L'1';
   1802         } else {
   1803           *TmpStr = L'0';
   1804         }
   1805 
   1806         //
   1807         // 3. Call the keyword handler protocol to change the value.
   1808         //
   1809         Status = PrivateData->HiiKeywordHandler->SetData (PrivateData->HiiKeywordHandler,
   1810                                                           Results,
   1811                                                           &Progress,
   1812                                                           &ProgressErr
   1813                                                          );
   1814         if (EFI_ERROR (Status)) {
   1815           do {
   1816             CreatePopUp (
   1817               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   1818               &Key,
   1819               L"",
   1820               L"Set keyword to the system failed!",
   1821               L"Press ENTER to continue ...",
   1822               L"",
   1823               NULL
   1824               );
   1825           } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
   1826 
   1827           Status = EFI_SUCCESS;
   1828           break;
   1829         }
   1830         break;
   1831 
   1832       default:
   1833       break;
   1834     }
   1835   break;
   1836 
   1837   default:
   1838     Status = EFI_UNSUPPORTED;
   1839     break;
   1840   }
   1841 
   1842   return Status;
   1843 }
   1844 
   1845 /**
   1846   Main entry for this driver.
   1847 
   1848   @param ImageHandle     Image handle this driver.
   1849   @param SystemTable     Pointer to SystemTable.
   1850 
   1851   @retval EFI_SUCESS     This function always complete successfully.
   1852 
   1853 **/
   1854 EFI_STATUS
   1855 EFIAPI
   1856 DriverSampleInit (
   1857   IN EFI_HANDLE                   ImageHandle,
   1858   IN EFI_SYSTEM_TABLE             *SystemTable
   1859   )
   1860 {
   1861   EFI_STATUS                      Status;
   1862   EFI_HII_HANDLE                  HiiHandle[2];
   1863   EFI_SCREEN_DESCRIPTOR           Screen;
   1864   EFI_HII_DATABASE_PROTOCOL       *HiiDatabase;
   1865   EFI_HII_STRING_PROTOCOL         *HiiString;
   1866   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
   1867   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
   1868   EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
   1869   CHAR16                          *NewString;
   1870   UINTN                           BufferSize;
   1871   DRIVER_SAMPLE_CONFIGURATION     *Configuration;
   1872   BOOLEAN                         ActionFlag;
   1873   EFI_STRING                      ConfigRequestHdr;
   1874   EFI_STRING                      NameRequestHdr;
   1875   MY_EFI_VARSTORE_DATA            *VarStoreConfig;
   1876   EFI_INPUT_KEY                   HotKey;
   1877   EFI_FORM_BROWSER_EXTENSION_PROTOCOL *FormBrowserEx;
   1878 
   1879   //
   1880   // Initialize the local variables.
   1881   //
   1882   ConfigRequestHdr = NULL;
   1883   NewString        = NULL;
   1884 
   1885   //
   1886   // Initialize screen dimensions for SendForm().
   1887   // Remove 3 characters from top and bottom
   1888   //
   1889   ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
   1890   gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
   1891 
   1892   Screen.TopRow     = 3;
   1893   Screen.BottomRow  = Screen.BottomRow - 3;
   1894 
   1895   //
   1896   // Initialize driver private data
   1897   //
   1898   mPrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
   1899   if (mPrivateData == NULL) {
   1900     return EFI_OUT_OF_RESOURCES;
   1901   }
   1902 
   1903   mPrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
   1904 
   1905   mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
   1906   mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
   1907   mPrivateData->ConfigAccess.Callback = DriverCallback;
   1908   mPrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
   1909 
   1910   //
   1911   // Locate Hii Database protocol
   1912   //
   1913   Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
   1914   if (EFI_ERROR (Status)) {
   1915     return Status;
   1916   }
   1917   mPrivateData->HiiDatabase = HiiDatabase;
   1918 
   1919   //
   1920   // Locate HiiString protocol
   1921   //
   1922   Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
   1923   if (EFI_ERROR (Status)) {
   1924     return Status;
   1925   }
   1926   mPrivateData->HiiString = HiiString;
   1927 
   1928   //
   1929   // Locate Formbrowser2 protocol
   1930   //
   1931   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
   1932   if (EFI_ERROR (Status)) {
   1933     return Status;
   1934   }
   1935   mPrivateData->FormBrowser2 = FormBrowser2;
   1936 
   1937   //
   1938   // Locate ConfigRouting protocol
   1939   //
   1940   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
   1941   if (EFI_ERROR (Status)) {
   1942     return Status;
   1943   }
   1944   mPrivateData->HiiConfigRouting = HiiConfigRouting;
   1945 
   1946   //
   1947   // Locate keyword handler protocol
   1948   //
   1949   Status = gBS->LocateProtocol (&gEfiConfigKeywordHandlerProtocolGuid, NULL, (VOID **) &HiiKeywordHandler);
   1950   if (EFI_ERROR (Status)) {
   1951     return Status;
   1952   }
   1953   mPrivateData->HiiKeywordHandler = HiiKeywordHandler;
   1954 
   1955   Status = gBS->InstallMultipleProtocolInterfaces (
   1956                   &DriverHandle[0],
   1957                   &gEfiDevicePathProtocolGuid,
   1958                   &mHiiVendorDevicePath0,
   1959                   &gEfiHiiConfigAccessProtocolGuid,
   1960                   &mPrivateData->ConfigAccess,
   1961                   NULL
   1962                   );
   1963   ASSERT_EFI_ERROR (Status);
   1964 
   1965   mPrivateData->DriverHandle[0] = DriverHandle[0];
   1966 
   1967   //
   1968   // Publish our HII data
   1969   //
   1970   HiiHandle[0] = HiiAddPackages (
   1971                    &gDriverSampleFormSetGuid,
   1972                    DriverHandle[0],
   1973                    DriverSampleStrings,
   1974                    VfrBin,
   1975                    NULL
   1976                    );
   1977   if (HiiHandle[0] == NULL) {
   1978     return EFI_OUT_OF_RESOURCES;
   1979   }
   1980 
   1981   mPrivateData->HiiHandle[0] = HiiHandle[0];
   1982 
   1983   //
   1984   // Publish another Fromset
   1985   //
   1986   Status = gBS->InstallMultipleProtocolInterfaces (
   1987                   &DriverHandle[1],
   1988                   &gEfiDevicePathProtocolGuid,
   1989                   &mHiiVendorDevicePath1,
   1990                   &gEfiHiiConfigAccessProtocolGuid,
   1991                   &mPrivateData->ConfigAccess,
   1992                   NULL
   1993                   );
   1994   ASSERT_EFI_ERROR (Status);
   1995 
   1996   mPrivateData->DriverHandle[1] = DriverHandle[1];
   1997 
   1998   HiiHandle[1] = HiiAddPackages (
   1999                    &gDriverSampleInventoryGuid,
   2000                    DriverHandle[1],
   2001                    DriverSampleStrings,
   2002                    InventoryBin,
   2003                    NULL
   2004                    );
   2005   if (HiiHandle[1] == NULL) {
   2006     DriverSampleUnload (ImageHandle);
   2007     return EFI_OUT_OF_RESOURCES;
   2008   }
   2009 
   2010   mPrivateData->HiiHandle[1] = HiiHandle[1];
   2011 
   2012   //
   2013   // Update the device path string.
   2014   //
   2015   NewString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)&mHiiVendorDevicePath0, FALSE, FALSE);
   2016   if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_DEVICE_PATH), NewString, NULL) == 0) {
   2017     DriverSampleUnload (ImageHandle);
   2018     return EFI_OUT_OF_RESOURCES;
   2019   }
   2020   if (NewString != NULL) {
   2021     FreePool (NewString);
   2022   }
   2023 
   2024   //
   2025   // Very simple example of how one would update a string that is already
   2026   // in the HII database
   2027   //
   2028   NewString = L"700 Mhz";
   2029 
   2030   if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
   2031     DriverSampleUnload (ImageHandle);
   2032     return EFI_OUT_OF_RESOURCES;
   2033   }
   2034 
   2035   HiiSetString (HiiHandle[0], 0, NewString, NULL);
   2036 
   2037   //
   2038   // Initialize Name/Value name String ID
   2039   //
   2040   mPrivateData->NameStringId[0] = STR_NAME_VALUE_VAR_NAME0;
   2041   mPrivateData->NameStringId[1] = STR_NAME_VALUE_VAR_NAME1;
   2042   mPrivateData->NameStringId[2] = STR_NAME_VALUE_VAR_NAME2;
   2043 
   2044   //
   2045   // Initialize configuration data
   2046   //
   2047   Configuration = &mPrivateData->Configuration;
   2048   ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
   2049 
   2050   //
   2051   // Try to read NV config EFI variable first
   2052   //
   2053   ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, DriverHandle[0]);
   2054   ASSERT (ConfigRequestHdr != NULL);
   2055 
   2056   NameRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, NULL, DriverHandle[0]);
   2057   ASSERT (NameRequestHdr != NULL);
   2058 
   2059   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
   2060   Status = gRT->GetVariable (VariableName, &gDriverSampleFormSetGuid, NULL, &BufferSize, Configuration);
   2061   if (EFI_ERROR (Status)) {
   2062     //
   2063     // Store zero data Buffer Storage to EFI variable
   2064     //
   2065     Status = gRT->SetVariable(
   2066                     VariableName,
   2067                     &gDriverSampleFormSetGuid,
   2068                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
   2069                     sizeof (DRIVER_SAMPLE_CONFIGURATION),
   2070                     Configuration
   2071                     );
   2072     if (EFI_ERROR (Status)) {
   2073       DriverSampleUnload (ImageHandle);
   2074       return Status;
   2075     }
   2076     //
   2077     // EFI variable for NV config doesn't exit, we should build this variable
   2078     // based on default values stored in IFR
   2079     //
   2080     ActionFlag = HiiSetToDefaults (NameRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
   2081     if (!ActionFlag) {
   2082       DriverSampleUnload (ImageHandle);
   2083       return EFI_INVALID_PARAMETER;
   2084     }
   2085 
   2086     ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
   2087     if (!ActionFlag) {
   2088       DriverSampleUnload (ImageHandle);
   2089       return EFI_INVALID_PARAMETER;
   2090     }
   2091   } else {
   2092     //
   2093     // EFI variable does exist and Validate Current Setting
   2094     //
   2095     ActionFlag = HiiValidateSettings (NameRequestHdr);
   2096     if (!ActionFlag) {
   2097       DriverSampleUnload (ImageHandle);
   2098       return EFI_INVALID_PARAMETER;
   2099     }
   2100 
   2101     ActionFlag = HiiValidateSettings (ConfigRequestHdr);
   2102     if (!ActionFlag) {
   2103       DriverSampleUnload (ImageHandle);
   2104       return EFI_INVALID_PARAMETER;
   2105     }
   2106   }
   2107   FreePool (ConfigRequestHdr);
   2108 
   2109   //
   2110   // Initialize efi varstore configuration data
   2111   //
   2112   VarStoreConfig = &mPrivateData->VarStoreConfig;
   2113   ZeroMem (VarStoreConfig, sizeof (MY_EFI_VARSTORE_DATA));
   2114 
   2115   ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, MyEfiVar, DriverHandle[0]);
   2116   ASSERT (ConfigRequestHdr != NULL);
   2117 
   2118   BufferSize = sizeof (MY_EFI_VARSTORE_DATA);
   2119   Status = gRT->GetVariable (MyEfiVar, &gDriverSampleFormSetGuid, NULL, &BufferSize, VarStoreConfig);
   2120   if (EFI_ERROR (Status)) {
   2121     //
   2122     // Store zero data to EFI variable Storage.
   2123     //
   2124     Status = gRT->SetVariable(
   2125                     MyEfiVar,
   2126                     &gDriverSampleFormSetGuid,
   2127                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
   2128                     sizeof (MY_EFI_VARSTORE_DATA),
   2129                     VarStoreConfig
   2130                     );
   2131     if (EFI_ERROR (Status)) {
   2132       DriverSampleUnload (ImageHandle);
   2133       return Status;
   2134     }
   2135     //
   2136     // EFI variable for NV config doesn't exit, we should build this variable
   2137     // based on default values stored in IFR
   2138     //
   2139     ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
   2140     if (!ActionFlag) {
   2141       DriverSampleUnload (ImageHandle);
   2142       return EFI_INVALID_PARAMETER;
   2143     }
   2144   } else {
   2145     //
   2146     // EFI variable does exist and Validate Current Setting
   2147     //
   2148     ActionFlag = HiiValidateSettings (ConfigRequestHdr);
   2149     if (!ActionFlag) {
   2150       DriverSampleUnload (ImageHandle);
   2151       return EFI_INVALID_PARAMETER;
   2152     }
   2153   }
   2154   FreePool (ConfigRequestHdr);
   2155 
   2156   Status = gBS->CreateEventEx (
   2157         EVT_NOTIFY_SIGNAL,
   2158         TPL_NOTIFY,
   2159         DriverSampleInternalEmptyFunction,
   2160         NULL,
   2161         &gEfiIfrRefreshIdOpGuid,
   2162         &mEvent
   2163         );
   2164   ASSERT_EFI_ERROR (Status);
   2165 
   2166   //
   2167   // Example of how to use BrowserEx protocol to register HotKey.
   2168   //
   2169   Status = gBS->LocateProtocol (&gEfiFormBrowserExProtocolGuid, NULL, (VOID **) &FormBrowserEx);
   2170   if (!EFI_ERROR (Status)) {
   2171     //
   2172     // First unregister the default hot key F9 and F10.
   2173     //
   2174     HotKey.UnicodeChar = CHAR_NULL;
   2175     HotKey.ScanCode    = SCAN_F9;
   2176     FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
   2177     HotKey.ScanCode    = SCAN_F10;
   2178     FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
   2179 
   2180     //
   2181     // Register the default HotKey F9 and F10 again.
   2182     //
   2183     HotKey.ScanCode   = SCAN_F10;
   2184     NewString         = HiiGetString (mPrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
   2185     ASSERT (NewString != NULL);
   2186     FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
   2187     HotKey.ScanCode   = SCAN_F9;
   2188     NewString         = HiiGetString (mPrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
   2189     ASSERT (NewString != NULL);
   2190     FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
   2191   }
   2192 
   2193   //
   2194   // In default, this driver is built into Flash device image,
   2195   // the following code doesn't run.
   2196   //
   2197 
   2198   //
   2199   // Example of how to display only the item we sent to HII
   2200   // When this driver is not built into Flash device image,
   2201   // it need to call SendForm to show front page by itself.
   2202   //
   2203   if (DISPLAY_ONLY_MY_ITEM <= 1) {
   2204     //
   2205     // Have the browser pull out our copy of the data, and only display our data
   2206     //
   2207     Status = FormBrowser2->SendForm (
   2208                              FormBrowser2,
   2209                              &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
   2210                              1,
   2211                              NULL,
   2212                              0,
   2213                              NULL,
   2214                              NULL
   2215                              );
   2216 
   2217     HiiRemovePackages (HiiHandle[0]);
   2218 
   2219     HiiRemovePackages (HiiHandle[1]);
   2220   }
   2221 
   2222   return EFI_SUCCESS;
   2223 }
   2224 
   2225 /**
   2226   Unloads the application and its installed protocol.
   2227 
   2228   @param[in]  ImageHandle       Handle that identifies the image to be unloaded.
   2229 
   2230   @retval EFI_SUCCESS           The image has been unloaded.
   2231 **/
   2232 EFI_STATUS
   2233 EFIAPI
   2234 DriverSampleUnload (
   2235   IN EFI_HANDLE  ImageHandle
   2236   )
   2237 {
   2238   UINTN Index;
   2239 
   2240   ASSERT (mPrivateData != NULL);
   2241 
   2242   if (DriverHandle[0] != NULL) {
   2243     gBS->UninstallMultipleProtocolInterfaces (
   2244             DriverHandle[0],
   2245             &gEfiDevicePathProtocolGuid,
   2246             &mHiiVendorDevicePath0,
   2247             &gEfiHiiConfigAccessProtocolGuid,
   2248             &mPrivateData->ConfigAccess,
   2249             NULL
   2250            );
   2251     DriverHandle[0] = NULL;
   2252   }
   2253 
   2254   if (DriverHandle[1] != NULL) {
   2255     gBS->UninstallMultipleProtocolInterfaces (
   2256             DriverHandle[1],
   2257             &gEfiDevicePathProtocolGuid,
   2258             &mHiiVendorDevicePath1,
   2259             NULL
   2260            );
   2261     DriverHandle[1] = NULL;
   2262   }
   2263 
   2264   if (mPrivateData->HiiHandle[0] != NULL) {
   2265     HiiRemovePackages (mPrivateData->HiiHandle[0]);
   2266   }
   2267 
   2268   if (mPrivateData->HiiHandle[1] != NULL) {
   2269     HiiRemovePackages (mPrivateData->HiiHandle[1]);
   2270   }
   2271 
   2272   for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {
   2273     if (mPrivateData->NameValueName[Index] != NULL) {
   2274       FreePool (mPrivateData->NameValueName[Index]);
   2275     }
   2276   }
   2277   FreePool (mPrivateData);
   2278   mPrivateData = NULL;
   2279 
   2280   gBS->CloseEvent (mEvent);
   2281 
   2282   return EFI_SUCCESS;
   2283 }
   2284