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
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   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
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   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
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     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
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     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
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         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
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   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
DriverSampleInit(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
DriverSampleUnload(IN EFI_HANDLE ImageHandle)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