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 - 2014, 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      *PrivateData = 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
DriverSampleInternalEmptyFunction(IN EFI_EVENT Event,IN VOID * Context)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
NotificationFunction(IN EFI_KEY_DATA * KeyData)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
InternalStartMonitor(VOID)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
InternalStopMonitor(VOID)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
EncodePassword(IN CHAR16 * Password,IN UINTN MaxSize)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
ValidatePassword(IN DRIVER_SAMPLE_PRIVATE_DATA * PrivateData,IN EFI_STRING_ID StringId)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   StrnCpy (EncodedPassword, 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
SetPassword(IN DRIVER_SAMPLE_PRIVATE_DATA * PrivateData,IN EFI_STRING_ID StringId)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   StrnCpy (Password, 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
LoadNameValueNames(IN DRIVER_SAMPLE_PRIVATE_DATA * PrivateData)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
GetValueOfNumber(IN EFI_STRING StringPtr,OUT UINT8 ** Number,OUT UINTN * Len)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
CreateAltCfgString(IN EFI_STRING Result,IN EFI_STRING ConfigHdr,IN UINTN Offset,IN UINTN Width)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     StrCpy (StringPtr, 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
AppendAltCfgString(IN OUT EFI_STRING * RequestResult,IN EFI_STRING ConfigRequestHdr)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
ExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)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     StrCpy (*Results, 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
RouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)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         StrnCpy (TemStr, 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
DriverCallback(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN EFI_BROWSER_ACTION Action,IN EFI_QUESTION_ID QuestionId,IN UINT8 Type,IN EFI_IFR_TYPE_VALUE * Value,OUT EFI_BROWSER_ACTION_REQUEST * ActionRequest)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 
1283   if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))||
1284     (ActionRequest == NULL)) {
1285     return EFI_INVALID_PARAMETER;
1286   }
1287 
1288 
1289   FormId = 0;
1290   Status = EFI_SUCCESS;
1291   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1292 
1293   switch (Action) {
1294   case EFI_BROWSER_ACTION_FORM_OPEN:
1295     {
1296       if (QuestionId == 0x1234) {
1297         //
1298         // Sample CallBack for UEFI FORM_OPEN action:
1299         //   Add Save action into Form 3 when Form 1 is opened.
1300         //   This will be done only in FORM_OPEN CallBack of question with ID 0x1234 from Form 1.
1301         //
1302         PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1303 
1304         //
1305         // Initialize the container for dynamic opcodes
1306         //
1307         StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1308         ASSERT (StartOpCodeHandle != NULL);
1309 
1310         //
1311         // Create Hii Extend Label OpCode as the start opcode
1312         //
1313         StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1314         StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1315         StartLabel->Number       = LABEL_UPDATE2;
1316 
1317         HiiCreateActionOpCode (
1318           StartOpCodeHandle,                // Container for dynamic created opcodes
1319           0x1238,                           // Question ID
1320           STRING_TOKEN(STR_SAVE_TEXT),      // Prompt text
1321           STRING_TOKEN(STR_SAVE_TEXT),      // Help text
1322           EFI_IFR_FLAG_CALLBACK,            // Question flag
1323           0                                 // Action String ID
1324         );
1325 
1326         HiiUpdateForm (
1327           PrivateData->HiiHandle[0],  // HII handle
1328           &gDriverSampleFormSetGuid,  // Formset GUID
1329           0x3,                        // Form ID
1330           StartOpCodeHandle,          // Label for where to insert opcodes
1331           NULL                        // Insert data
1332           );
1333 
1334         HiiFreeOpCodeHandle (StartOpCodeHandle);
1335       }
1336 
1337       if (QuestionId == 0x1247) {
1338         Status = InternalStartMonitor ();
1339         ASSERT_EFI_ERROR (Status);
1340       }
1341     }
1342     break;
1343 
1344   case EFI_BROWSER_ACTION_FORM_CLOSE:
1345     {
1346       if (QuestionId == 0x5678) {
1347         //
1348         // Sample CallBack for UEFI FORM_CLOSE action:
1349         //   Show up a pop-up to specify Form 3 will be closed when exit Form 3.
1350         //
1351         do {
1352           CreatePopUp (
1353             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1354             &Key,
1355             L"",
1356             L"You are going to leave third Form!",
1357             L"Press ESC or ENTER to continue ...",
1358             L"",
1359             NULL
1360             );
1361         } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1362       }
1363 
1364       if (QuestionId == 0x1247) {
1365         Status = InternalStopMonitor ();
1366         ASSERT_EFI_ERROR (Status);
1367       }
1368     }
1369     break;
1370 
1371   case EFI_BROWSER_ACTION_RETRIEVE:
1372     {
1373       if (QuestionId == 0x1248) {
1374         {
1375           if (Type != EFI_IFR_TYPE_REF) {
1376             return EFI_INVALID_PARAMETER;
1377           }
1378 
1379           Value->ref.FormId = 0x3;
1380         }
1381       }
1382     }
1383     break;
1384 
1385   case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
1386     {
1387       switch (QuestionId) {
1388       case 0x1240:
1389         Value->u8 = DEFAULT_CLASS_STANDARD_VALUE;
1390       break;
1391 
1392       default:
1393         Status = EFI_UNSUPPORTED;
1394       break;
1395       }
1396     }
1397     break;
1398 
1399   case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
1400     {
1401       switch (QuestionId) {
1402       case 0x1240:
1403         Value->u8 = DEFAULT_CLASS_MANUFACTURING_VALUE;
1404       break;
1405 
1406       default:
1407         Status = EFI_UNSUPPORTED;
1408       break;
1409       }
1410     }
1411     break;
1412 
1413   case EFI_BROWSER_ACTION_CHANGING:
1414   {
1415     switch (QuestionId) {
1416     case 0x1249:
1417       {
1418         if (Type != EFI_IFR_TYPE_REF) {
1419           return EFI_INVALID_PARAMETER;
1420         }
1421 
1422         Value->ref.FormId = 0x1234;
1423       }
1424     break;
1425     case 0x1234:
1426       //
1427       // Initialize the container for dynamic opcodes
1428       //
1429       StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1430       ASSERT (StartOpCodeHandle != NULL);
1431 
1432       EndOpCodeHandle = HiiAllocateOpCodeHandle ();
1433       ASSERT (EndOpCodeHandle != NULL);
1434 
1435       //
1436       // Create Hii Extend Label OpCode as the start opcode
1437       //
1438       StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1439       StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1440       StartLabel->Number       = LABEL_UPDATE1;
1441 
1442       //
1443       // Create Hii Extend Label OpCode as the end opcode
1444       //
1445       EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1446       EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1447       EndLabel->Number       = LABEL_END;
1448 
1449       HiiCreateActionOpCode (
1450         StartOpCodeHandle,                // Container for dynamic created opcodes
1451         0x1237,                           // Question ID
1452         STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text
1453         STRING_TOKEN(STR_EXIT_TEXT),      // Help text
1454         EFI_IFR_FLAG_CALLBACK,            // Question flag
1455         0                                 // Action String ID
1456       );
1457 
1458       //
1459       // Create Option OpCode
1460       //
1461       OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
1462       ASSERT (OptionsOpCodeHandle != NULL);
1463 
1464       HiiCreateOneOfOptionOpCode (
1465         OptionsOpCodeHandle,
1466         STRING_TOKEN (STR_BOOT_OPTION1),
1467         0,
1468         EFI_IFR_NUMERIC_SIZE_1,
1469         1
1470         );
1471 
1472       HiiCreateOneOfOptionOpCode (
1473         OptionsOpCodeHandle,
1474         STRING_TOKEN (STR_BOOT_OPTION2),
1475         0,
1476         EFI_IFR_NUMERIC_SIZE_1,
1477         2
1478         );
1479 
1480       //
1481       // Prepare initial value for the dynamic created oneof Question
1482       //
1483       PrivateData->Configuration.DynamicOneof = 2;
1484       Status = gRT->SetVariable(
1485                       VariableName,
1486                       &gDriverSampleFormSetGuid,
1487                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1488                       sizeof (DRIVER_SAMPLE_CONFIGURATION),
1489                       &PrivateData->Configuration
1490                       );
1491 
1492       //
1493       // Set initial vlaue of dynamic created oneof Question in Form Browser
1494       //
1495       Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
1496       ASSERT (Configuration != NULL);
1497       if (HiiGetBrowserData (&gDriverSampleFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
1498         Configuration->DynamicOneof = 2;
1499 
1500         //
1501         // Update uncommitted data of Browser
1502         //
1503         HiiSetBrowserData (
1504           &gDriverSampleFormSetGuid,
1505           VariableName,
1506           sizeof (DRIVER_SAMPLE_CONFIGURATION),
1507           (UINT8 *) Configuration,
1508           NULL
1509           );
1510       }
1511       FreePool (Configuration);
1512 
1513       HiiCreateOneOfOpCode (
1514         StartOpCodeHandle,                         // Container for dynamic created opcodes
1515         0x8001,                                    // Question ID (or call it "key")
1516         CONFIGURATION_VARSTORE_ID,                 // VarStore ID
1517         (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET,        // Offset in Buffer Storage
1518         STRING_TOKEN (STR_ONE_OF_PROMPT),          // Question prompt text
1519         STRING_TOKEN (STR_ONE_OF_HELP),            // Question help text
1520         EFI_IFR_FLAG_CALLBACK,                     // Question flag
1521         EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question Value
1522         OptionsOpCodeHandle,                       // Option Opcode list
1523         NULL                                       // Default Opcode is NULl
1524         );
1525 
1526       HiiCreateOrderedListOpCode (
1527         StartOpCodeHandle,                         // Container for dynamic created opcodes
1528         0x8002,                                    // Question ID
1529         CONFIGURATION_VARSTORE_ID,                 // VarStore ID
1530         (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET,  // Offset in Buffer Storage
1531         STRING_TOKEN (STR_BOOT_OPTIONS),           // Question prompt text
1532         STRING_TOKEN (STR_BOOT_OPTIONS),           // Question help text
1533         EFI_IFR_FLAG_RESET_REQUIRED,               // Question flag
1534         0,                                         // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1535         EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question value
1536         5,                                         // Maximum container
1537         OptionsOpCodeHandle,                       // Option Opcode list
1538         NULL                                       // Default Opcode is NULl
1539         );
1540 
1541       HiiCreateTextOpCode (
1542         StartOpCodeHandle,
1543         STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
1544         STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
1545         STRING_TOKEN(STR_TEXT_SAMPLE_STRING)
1546       );
1547 
1548       HiiCreateDateOpCode (
1549         StartOpCodeHandle,
1550         0x8004,
1551         0x0,
1552         0x0,
1553         STRING_TOKEN(STR_DATE_SAMPLE_HELP),
1554         STRING_TOKEN(STR_DATE_SAMPLE_HELP),
1555         0,
1556         QF_DATE_STORAGE_TIME,
1557         NULL
1558         );
1559 
1560       HiiCreateTimeOpCode (
1561         StartOpCodeHandle,
1562         0x8005,
1563         0x0,
1564         0x0,
1565         STRING_TOKEN(STR_TIME_SAMPLE_HELP),
1566         STRING_TOKEN(STR_TIME_SAMPLE_HELP),
1567         0,
1568         QF_TIME_STORAGE_TIME,
1569         NULL
1570         );
1571 
1572       HiiCreateGotoOpCode (
1573         StartOpCodeHandle,                // Container for dynamic created opcodes
1574         1,                                // Target Form ID
1575         STRING_TOKEN (STR_GOTO_FORM1),    // Prompt text
1576         STRING_TOKEN (STR_GOTO_HELP),     // Help text
1577         0,                                // Question flag
1578         0x8003                            // Question ID
1579         );
1580 
1581       HiiUpdateForm (
1582         PrivateData->HiiHandle[0],  // HII handle
1583         &gDriverSampleFormSetGuid,  // Formset GUID
1584         0x1234,                     // Form ID
1585         StartOpCodeHandle,          // Label for where to insert opcodes
1586         EndOpCodeHandle             // Replace data
1587         );
1588 
1589       HiiFreeOpCodeHandle (StartOpCodeHandle);
1590       HiiFreeOpCodeHandle (OptionsOpCodeHandle);
1591       HiiFreeOpCodeHandle (EndOpCodeHandle);
1592       break;
1593 
1594     case 0x5678:
1595     case 0x1247:
1596       //
1597       // We will reach here once the Question is refreshed
1598       //
1599 
1600       //
1601       // Initialize the container for dynamic opcodes
1602       //
1603       StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1604       ASSERT (StartOpCodeHandle != NULL);
1605 
1606       //
1607       // Create Hii Extend Label OpCode as the start opcode
1608       //
1609       StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1610       StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1611       if (QuestionId == 0x5678) {
1612         StartLabel->Number       = LABEL_UPDATE2;
1613         FormId                   = 0x03;
1614         PrivateData->Configuration.DynamicRefresh++;
1615       } else if (QuestionId == 0x1247 ) {
1616         StartLabel->Number       = LABEL_UPDATE3;
1617         FormId                   = 0x06;
1618         PrivateData->Configuration.RefreshGuidCount++;
1619       }
1620 
1621       HiiCreateActionOpCode (
1622         StartOpCodeHandle,                // Container for dynamic created opcodes
1623         0x1237,                           // Question ID
1624         STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text
1625         STRING_TOKEN(STR_EXIT_TEXT),      // Help text
1626         EFI_IFR_FLAG_CALLBACK,            // Question flag
1627         0                                 // Action String ID
1628       );
1629 
1630       HiiUpdateForm (
1631         PrivateData->HiiHandle[0],  // HII handle
1632         &gDriverSampleFormSetGuid,              // Formset GUID
1633         FormId,                        // Form ID
1634         StartOpCodeHandle,          // Label for where to insert opcodes
1635         NULL                        // Insert data
1636         );
1637 
1638       HiiFreeOpCodeHandle (StartOpCodeHandle);
1639 
1640       //
1641       // Refresh the Question value
1642       //
1643       Status = gRT->SetVariable(
1644                       VariableName,
1645                       &gDriverSampleFormSetGuid,
1646                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1647                       sizeof (DRIVER_SAMPLE_CONFIGURATION),
1648                       &PrivateData->Configuration
1649                       );
1650 
1651       if (QuestionId == 0x5678) {
1652         //
1653         // Update uncommitted data of Browser
1654         //
1655         EfiData = AllocateZeroPool (sizeof (MY_EFI_VARSTORE_DATA));
1656         ASSERT (EfiData != NULL);
1657         if (HiiGetBrowserData (&gDriverSampleFormSetGuid, MyEfiVar, sizeof (MY_EFI_VARSTORE_DATA), (UINT8 *) EfiData)) {
1658           EfiData->Field8 = 111;
1659           HiiSetBrowserData (
1660             &gDriverSampleFormSetGuid,
1661             MyEfiVar,
1662             sizeof (MY_EFI_VARSTORE_DATA),
1663             (UINT8 *) EfiData,
1664             NULL
1665             );
1666         }
1667         FreePool (EfiData);
1668       }
1669       break;
1670 
1671     case 0x2000:
1672       //
1673       // Only used to update the state.
1674       //
1675       if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0) &&
1676         (PrivateData->PasswordState == BROWSER_STATE_SET_PASSWORD)) {
1677         PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1678         return EFI_INVALID_PARAMETER;
1679       }
1680 
1681       //
1682       // When try to set a new password, user will be chanlleged with old password.
1683       // The Callback is responsible for validating old password input by user,
1684       // If Callback return EFI_SUCCESS, it indicates validation pass.
1685       //
1686       switch (PrivateData->PasswordState) {
1687       case BROWSER_STATE_VALIDATE_PASSWORD:
1688         Status = ValidatePassword (PrivateData, Value->string);
1689         if (Status == EFI_SUCCESS) {
1690           PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
1691         }
1692         break;
1693 
1694       case BROWSER_STATE_SET_PASSWORD:
1695         Status = SetPassword (PrivateData, Value->string);
1696         PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1697         break;
1698 
1699       default:
1700         break;
1701       }
1702 
1703       break;
1704 
1705     default:
1706       break;
1707     }
1708   }
1709   break;
1710 
1711   case EFI_BROWSER_ACTION_CHANGED:
1712     switch (QuestionId) {
1713       case 0x1237:
1714         //
1715         // User press "Exit now", request Browser to exit
1716         //
1717         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
1718         break;
1719 
1720       case 0x1238:
1721         //
1722         // User press "Save now", request Browser to save the uncommitted data.
1723         //
1724         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1725         break;
1726 
1727       case 0x1241:
1728       case 0x1246:
1729         //
1730         // User press "Submit current form and Exit now", request Browser to submit current form and exit
1731         //
1732         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
1733         break;
1734 
1735       case 0x1242:
1736         //
1737         // User press "Discard current form now", request Browser to discard the uncommitted data.
1738         //
1739         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD;
1740         break;
1741 
1742       case 0x1243:
1743         //
1744         // User press "Submit current form now", request Browser to save the uncommitted data.
1745         //
1746         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
1747         break;
1748 
1749       case 0x1244:
1750       case 0x1245:
1751         //
1752         // User press "Discard current form and Exit now", request Browser to discard the uncommitted data and exit.
1753         //
1754         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
1755         break;
1756 
1757       default:
1758       break;
1759     }
1760   break;
1761 
1762   default:
1763     Status = EFI_UNSUPPORTED;
1764     break;
1765   }
1766 
1767   return Status;
1768 }
1769 
1770 /**
1771   Main entry for this driver.
1772 
1773   @param ImageHandle     Image handle this driver.
1774   @param SystemTable     Pointer to SystemTable.
1775 
1776   @retval EFI_SUCESS     This function always complete successfully.
1777 
1778 **/
1779 EFI_STATUS
1780 EFIAPI
DriverSampleInit(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1781 DriverSampleInit (
1782   IN EFI_HANDLE                   ImageHandle,
1783   IN EFI_SYSTEM_TABLE             *SystemTable
1784   )
1785 {
1786   EFI_STATUS                      Status;
1787   EFI_HII_HANDLE                  HiiHandle[2];
1788   EFI_SCREEN_DESCRIPTOR           Screen;
1789   EFI_HII_DATABASE_PROTOCOL       *HiiDatabase;
1790   EFI_HII_STRING_PROTOCOL         *HiiString;
1791   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
1792   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1793   CHAR16                          *NewString;
1794   UINTN                           BufferSize;
1795   DRIVER_SAMPLE_CONFIGURATION     *Configuration;
1796   BOOLEAN                         ActionFlag;
1797   EFI_STRING                      ConfigRequestHdr;
1798   EFI_STRING                      NameRequestHdr;
1799   MY_EFI_VARSTORE_DATA            *VarStoreConfig;
1800   EFI_INPUT_KEY                   HotKey;
1801   EFI_FORM_BROWSER_EXTENSION_PROTOCOL *FormBrowserEx;
1802 
1803   //
1804   // Initialize the local variables.
1805   //
1806   ConfigRequestHdr = NULL;
1807   NewString        = NULL;
1808 
1809   //
1810   // Initialize screen dimensions for SendForm().
1811   // Remove 3 characters from top and bottom
1812   //
1813   ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
1814   gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
1815 
1816   Screen.TopRow     = 3;
1817   Screen.BottomRow  = Screen.BottomRow - 3;
1818 
1819   //
1820   // Initialize driver private data
1821   //
1822   PrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
1823   if (PrivateData == NULL) {
1824     return EFI_OUT_OF_RESOURCES;
1825   }
1826 
1827   PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
1828 
1829   PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
1830   PrivateData->ConfigAccess.RouteConfig = RouteConfig;
1831   PrivateData->ConfigAccess.Callback = DriverCallback;
1832   PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1833 
1834   //
1835   // Locate Hii Database protocol
1836   //
1837   Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
1838   if (EFI_ERROR (Status)) {
1839     return Status;
1840   }
1841   PrivateData->HiiDatabase = HiiDatabase;
1842 
1843   //
1844   // Locate HiiString protocol
1845   //
1846   Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
1847   if (EFI_ERROR (Status)) {
1848     return Status;
1849   }
1850   PrivateData->HiiString = HiiString;
1851 
1852   //
1853   // Locate Formbrowser2 protocol
1854   //
1855   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
1856   if (EFI_ERROR (Status)) {
1857     return Status;
1858   }
1859   PrivateData->FormBrowser2 = FormBrowser2;
1860 
1861   //
1862   // Locate ConfigRouting protocol
1863   //
1864   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
1865   if (EFI_ERROR (Status)) {
1866     return Status;
1867   }
1868   PrivateData->HiiConfigRouting = HiiConfigRouting;
1869 
1870   Status = gBS->InstallMultipleProtocolInterfaces (
1871                   &DriverHandle[0],
1872                   &gEfiDevicePathProtocolGuid,
1873                   &mHiiVendorDevicePath0,
1874                   &gEfiHiiConfigAccessProtocolGuid,
1875                   &PrivateData->ConfigAccess,
1876                   NULL
1877                   );
1878   ASSERT_EFI_ERROR (Status);
1879 
1880   PrivateData->DriverHandle[0] = DriverHandle[0];
1881 
1882   //
1883   // Publish our HII data
1884   //
1885   HiiHandle[0] = HiiAddPackages (
1886                    &gDriverSampleFormSetGuid,
1887                    DriverHandle[0],
1888                    DriverSampleStrings,
1889                    VfrBin,
1890                    NULL
1891                    );
1892   if (HiiHandle[0] == NULL) {
1893     return EFI_OUT_OF_RESOURCES;
1894   }
1895 
1896   PrivateData->HiiHandle[0] = HiiHandle[0];
1897 
1898   //
1899   // Publish another Fromset
1900   //
1901   Status = gBS->InstallMultipleProtocolInterfaces (
1902                   &DriverHandle[1],
1903                   &gEfiDevicePathProtocolGuid,
1904                   &mHiiVendorDevicePath1,
1905                   NULL
1906                   );
1907   ASSERT_EFI_ERROR (Status);
1908 
1909   PrivateData->DriverHandle[1] = DriverHandle[1];
1910 
1911   HiiHandle[1] = HiiAddPackages (
1912                    &gDriverSampleInventoryGuid,
1913                    DriverHandle[1],
1914                    DriverSampleStrings,
1915                    InventoryBin,
1916                    NULL
1917                    );
1918   if (HiiHandle[1] == NULL) {
1919     DriverSampleUnload (ImageHandle);
1920     return EFI_OUT_OF_RESOURCES;
1921   }
1922 
1923   PrivateData->HiiHandle[1] = HiiHandle[1];
1924 
1925   //
1926   // Update the device path string.
1927   //
1928   NewString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)&mHiiVendorDevicePath0, FALSE, FALSE);
1929   if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_DEVICE_PATH), NewString, NULL) == 0) {
1930     DriverSampleUnload (ImageHandle);
1931     return EFI_OUT_OF_RESOURCES;
1932   }
1933   if (NewString != NULL) {
1934     FreePool (NewString);
1935   }
1936 
1937   //
1938   // Very simple example of how one would update a string that is already
1939   // in the HII database
1940   //
1941   NewString = L"700 Mhz";
1942 
1943   if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
1944     DriverSampleUnload (ImageHandle);
1945     return EFI_OUT_OF_RESOURCES;
1946   }
1947 
1948   HiiSetString (HiiHandle[0], 0, NewString, NULL);
1949 
1950   //
1951   // Initialize Name/Value name String ID
1952   //
1953   PrivateData->NameStringId[0] = STR_NAME_VALUE_VAR_NAME0;
1954   PrivateData->NameStringId[1] = STR_NAME_VALUE_VAR_NAME1;
1955   PrivateData->NameStringId[2] = STR_NAME_VALUE_VAR_NAME2;
1956 
1957   //
1958   // Initialize configuration data
1959   //
1960   Configuration = &PrivateData->Configuration;
1961   ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
1962 
1963   //
1964   // Try to read NV config EFI variable first
1965   //
1966   ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, DriverHandle[0]);
1967   ASSERT (ConfigRequestHdr != NULL);
1968 
1969   NameRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, NULL, DriverHandle[0]);
1970   ASSERT (NameRequestHdr != NULL);
1971 
1972   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1973   Status = gRT->GetVariable (VariableName, &gDriverSampleFormSetGuid, NULL, &BufferSize, Configuration);
1974   if (EFI_ERROR (Status)) {
1975     //
1976     // Store zero data Buffer Storage to EFI variable
1977     //
1978     Status = gRT->SetVariable(
1979                     VariableName,
1980                     &gDriverSampleFormSetGuid,
1981                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1982                     sizeof (DRIVER_SAMPLE_CONFIGURATION),
1983                     Configuration
1984                     );
1985     if (EFI_ERROR (Status)) {
1986       DriverSampleUnload (ImageHandle);
1987       return Status;
1988     }
1989     //
1990     // EFI variable for NV config doesn't exit, we should build this variable
1991     // based on default values stored in IFR
1992     //
1993     ActionFlag = HiiSetToDefaults (NameRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
1994     if (!ActionFlag) {
1995       DriverSampleUnload (ImageHandle);
1996       return EFI_INVALID_PARAMETER;
1997     }
1998 
1999     ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2000     if (!ActionFlag) {
2001       DriverSampleUnload (ImageHandle);
2002       return EFI_INVALID_PARAMETER;
2003     }
2004   } else {
2005     //
2006     // EFI variable does exist and Validate Current Setting
2007     //
2008     ActionFlag = HiiValidateSettings (NameRequestHdr);
2009     if (!ActionFlag) {
2010       DriverSampleUnload (ImageHandle);
2011       return EFI_INVALID_PARAMETER;
2012     }
2013 
2014     ActionFlag = HiiValidateSettings (ConfigRequestHdr);
2015     if (!ActionFlag) {
2016       DriverSampleUnload (ImageHandle);
2017       return EFI_INVALID_PARAMETER;
2018     }
2019   }
2020   FreePool (ConfigRequestHdr);
2021 
2022   //
2023   // Initialize efi varstore configuration data
2024   //
2025   VarStoreConfig = &PrivateData->VarStoreConfig;
2026   ZeroMem (VarStoreConfig, sizeof (MY_EFI_VARSTORE_DATA));
2027 
2028   ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, MyEfiVar, DriverHandle[0]);
2029   ASSERT (ConfigRequestHdr != NULL);
2030 
2031   BufferSize = sizeof (MY_EFI_VARSTORE_DATA);
2032   Status = gRT->GetVariable (MyEfiVar, &gDriverSampleFormSetGuid, NULL, &BufferSize, VarStoreConfig);
2033   if (EFI_ERROR (Status)) {
2034     //
2035     // Store zero data to EFI variable Storage.
2036     //
2037     Status = gRT->SetVariable(
2038                     MyEfiVar,
2039                     &gDriverSampleFormSetGuid,
2040                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
2041                     sizeof (MY_EFI_VARSTORE_DATA),
2042                     VarStoreConfig
2043                     );
2044     if (EFI_ERROR (Status)) {
2045       DriverSampleUnload (ImageHandle);
2046       return Status;
2047     }
2048     //
2049     // EFI variable for NV config doesn't exit, we should build this variable
2050     // based on default values stored in IFR
2051     //
2052     ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2053     if (!ActionFlag) {
2054       DriverSampleUnload (ImageHandle);
2055       return EFI_INVALID_PARAMETER;
2056     }
2057   } else {
2058     //
2059     // EFI variable does exist and Validate Current Setting
2060     //
2061     ActionFlag = HiiValidateSettings (ConfigRequestHdr);
2062     if (!ActionFlag) {
2063       DriverSampleUnload (ImageHandle);
2064       return EFI_INVALID_PARAMETER;
2065     }
2066   }
2067   FreePool (ConfigRequestHdr);
2068 
2069   Status = gBS->CreateEventEx (
2070         EVT_NOTIFY_SIGNAL,
2071         TPL_NOTIFY,
2072         DriverSampleInternalEmptyFunction,
2073         NULL,
2074         &gEfiIfrRefreshIdOpGuid,
2075         &mEvent
2076         );
2077   ASSERT_EFI_ERROR (Status);
2078 
2079   //
2080   // Example of how to use BrowserEx protocol to register HotKey.
2081   //
2082   Status = gBS->LocateProtocol (&gEfiFormBrowserExProtocolGuid, NULL, (VOID **) &FormBrowserEx);
2083   if (!EFI_ERROR (Status)) {
2084     //
2085     // First unregister the default hot key F9 and F10.
2086     //
2087     HotKey.UnicodeChar = CHAR_NULL;
2088     HotKey.ScanCode    = SCAN_F9;
2089     FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
2090     HotKey.ScanCode    = SCAN_F10;
2091     FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
2092 
2093     //
2094     // Register the default HotKey F9 and F10 again.
2095     //
2096     HotKey.ScanCode   = SCAN_F10;
2097     NewString         = HiiGetString (PrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
2098     ASSERT (NewString != NULL);
2099     FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
2100     HotKey.ScanCode   = SCAN_F9;
2101     NewString         = HiiGetString (PrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
2102     ASSERT (NewString != NULL);
2103     FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
2104   }
2105 
2106   //
2107   // In default, this driver is built into Flash device image,
2108   // the following code doesn't run.
2109   //
2110 
2111   //
2112   // Example of how to display only the item we sent to HII
2113   // When this driver is not built into Flash device image,
2114   // it need to call SendForm to show front page by itself.
2115   //
2116   if (DISPLAY_ONLY_MY_ITEM <= 1) {
2117     //
2118     // Have the browser pull out our copy of the data, and only display our data
2119     //
2120     Status = FormBrowser2->SendForm (
2121                              FormBrowser2,
2122                              &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
2123                              1,
2124                              NULL,
2125                              0,
2126                              NULL,
2127                              NULL
2128                              );
2129 
2130     HiiRemovePackages (HiiHandle[0]);
2131 
2132     HiiRemovePackages (HiiHandle[1]);
2133   }
2134 
2135   return EFI_SUCCESS;
2136 }
2137 
2138 /**
2139   Unloads the application and its installed protocol.
2140 
2141   @param[in]  ImageHandle       Handle that identifies the image to be unloaded.
2142 
2143   @retval EFI_SUCCESS           The image has been unloaded.
2144 **/
2145 EFI_STATUS
2146 EFIAPI
DriverSampleUnload(IN EFI_HANDLE ImageHandle)2147 DriverSampleUnload (
2148   IN EFI_HANDLE  ImageHandle
2149   )
2150 {
2151   UINTN Index;
2152 
2153   ASSERT (PrivateData != NULL);
2154 
2155   if (DriverHandle[0] != NULL) {
2156     gBS->UninstallMultipleProtocolInterfaces (
2157             DriverHandle[0],
2158             &gEfiDevicePathProtocolGuid,
2159             &mHiiVendorDevicePath0,
2160             &gEfiHiiConfigAccessProtocolGuid,
2161             &PrivateData->ConfigAccess,
2162             NULL
2163            );
2164     DriverHandle[0] = NULL;
2165   }
2166 
2167   if (DriverHandle[1] != NULL) {
2168     gBS->UninstallMultipleProtocolInterfaces (
2169             DriverHandle[1],
2170             &gEfiDevicePathProtocolGuid,
2171             &mHiiVendorDevicePath1,
2172             NULL
2173            );
2174     DriverHandle[1] = NULL;
2175   }
2176 
2177   if (PrivateData->HiiHandle[0] != NULL) {
2178     HiiRemovePackages (PrivateData->HiiHandle[0]);
2179   }
2180 
2181   if (PrivateData->HiiHandle[1] != NULL) {
2182     HiiRemovePackages (PrivateData->HiiHandle[1]);
2183   }
2184 
2185   for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {
2186     if (PrivateData->NameValueName[Index] != NULL) {
2187       FreePool (PrivateData->NameValueName[Index]);
2188     }
2189   }
2190   FreePool (PrivateData);
2191   PrivateData = NULL;
2192 
2193   gBS->CloseEvent (mEvent);
2194 
2195   return EFI_SUCCESS;
2196 }
2197