Update HiiConfigAccess.ExtractConfig interface to support NULL request string and...
[efi/edk2/.git] / edk2 / MdeModulePkg / Universal / DriverSampleDxe / DriverSample.c
1 /** @file\r
2 This is an example of how a driver might export data to the HII protocol to be\r
3 later utilized by the Setup Protocol\r
4 \r
5 Copyright (c) 2004 - 2010, Intel Corporation\r
6 All rights reserved. This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution.  The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10 \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 \r
14 **/\r
15 \r
16 \r
17 #include "DriverSample.h"\r
18 \r
19 #define DISPLAY_ONLY_MY_ITEM  0x0002\r
20 \r
21 EFI_GUID   mFormSetGuid = FORMSET_GUID;\r
22 EFI_GUID   mInventoryGuid = INVENTORY_GUID;\r
23 \r
24 CHAR16     VariableName[] = L"MyIfrNVData";\r
25 EFI_HANDLE                      DriverHandle[2] = {NULL, NULL};\r
26 DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData = NULL;\r
27 \r
28 HII_VENDOR_DEVICE_PATH  mHiiVendorDevicePath0 = {\r
29   {\r
30     {\r
31       HARDWARE_DEVICE_PATH,\r
32       HW_VENDOR_DP,\r
33       {\r
34         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
35         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
36       }\r
37     },\r
38     //\r
39     // {C153B68D-EBFC-488e-B110-662867745B87}\r
40     //\r
41     { 0xc153b68d, 0xebfc, 0x488e, { 0xb1, 0x10, 0x66, 0x28, 0x67, 0x74, 0x5b, 0x87 } }\r
42   },\r
43   {\r
44     END_DEVICE_PATH_TYPE,\r
45     END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
46     {\r
47       (UINT8) (END_DEVICE_PATH_LENGTH),\r
48       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
49     }\r
50   }\r
51 };\r
52 \r
53 HII_VENDOR_DEVICE_PATH  mHiiVendorDevicePath1 = {\r
54   {\r
55     {\r
56       HARDWARE_DEVICE_PATH,\r
57       HW_VENDOR_DP,\r
58       {\r
59         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
60         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
61       }\r
62     },\r
63     //\r
64     // {06F37F07-0C48-40e9-8436-0A08A0BB76B0}\r
65     //\r
66     { 0x6f37f07, 0xc48, 0x40e9, { 0x84, 0x36, 0xa, 0x8, 0xa0, 0xbb, 0x76, 0xb0 } }\r
67   },\r
68   {\r
69     END_DEVICE_PATH_TYPE,\r
70     END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
71     {\r
72       (UINT8) (END_DEVICE_PATH_LENGTH),\r
73       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
74     }\r
75   }\r
76 };\r
77 \r
78 /**\r
79   Encode the password using a simple algorithm.\r
80 \r
81   @param Password The string to be encoded.\r
82   @param MaxSize  The size of the string.\r
83 \r
84 **/\r
85 VOID\r
86 EncodePassword (\r
87   IN  CHAR16                      *Password,\r
88   IN  UINTN                       MaxSize\r
89   )\r
90 {\r
91   UINTN   Index;\r
92   UINTN   Loop;\r
93   CHAR16  *Buffer;\r
94   CHAR16  *Key;\r
95 \r
96   Key     = L"MAR10648567";\r
97   Buffer  = AllocateZeroPool (MaxSize);\r
98   ASSERT (Buffer != NULL);\r
99 \r
100   for (Index = 0; Key[Index] != 0; Index++) {\r
101     for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {\r
102       Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);\r
103     }\r
104   }\r
105 \r
106   CopyMem (Password, Buffer, MaxSize);\r
107 \r
108   FreePool (Buffer);\r
109   return ;\r
110 }\r
111 \r
112 /**\r
113   Validate the user's password.\r
114 \r
115   @param PrivateData This driver's private context data.\r
116   @param StringId    The user's input.\r
117 \r
118   @retval EFI_SUCCESS   The user's input matches the password.\r
119   @retval EFI_NOT_READY The user's input does not match the password.\r
120 **/\r
121 EFI_STATUS\r
122 ValidatePassword (\r
123   IN       DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData,\r
124   IN       EFI_STRING_ID                   StringId\r
125   )\r
126 {\r
127   EFI_STATUS                      Status;\r
128   UINTN                           Index;\r
129   UINTN                           BufferSize;\r
130   UINTN                           PasswordMaxSize;\r
131   CHAR16                          *Password;\r
132   CHAR16                          *EncodedPassword;\r
133   BOOLEAN                         OldPassword;\r
134 \r
135   //\r
136   // Get encoded password first\r
137   //\r
138   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
139   Status = gRT->GetVariable (\r
140                   VariableName,\r
141                   &mFormSetGuid,\r
142                   NULL,\r
143                   &BufferSize,\r
144                   &PrivateData->Configuration\r
145                   );\r
146   if (EFI_ERROR (Status)) {\r
147     //\r
148     // Old password not exist, prompt for new password\r
149     //\r
150     return EFI_SUCCESS;\r
151   }\r
152 \r
153   OldPassword = FALSE;\r
154   PasswordMaxSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);\r
155   //\r
156   // Check whether we have any old password set\r
157   //\r
158   for (Index = 0; Index < PasswordMaxSize / sizeof (UINT16); Index++) {\r
159     if (PrivateData->Configuration.WhatIsThePassword2[Index] != 0) {\r
160       OldPassword = TRUE;\r
161       break;\r
162     }\r
163   }\r
164   if (!OldPassword) {\r
165     //\r
166     // Old password not exist, return EFI_SUCCESS to prompt for new password\r
167     //\r
168     return EFI_SUCCESS;\r
169   }\r
170 \r
171   //\r
172   // Get user input password\r
173   //\r
174   Password = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);\r
175   if (Password == NULL) {\r
176     return EFI_NOT_READY;\r
177   }\r
178   if (StrSize (Password) > PasswordMaxSize) {\r
179     FreePool (Password);\r
180     return EFI_NOT_READY;\r
181   }\r
182 \r
183   //\r
184   // Validate old password\r
185   //\r
186   EncodedPassword = AllocateZeroPool (PasswordMaxSize);\r
187   ASSERT (EncodedPassword != NULL);\r
188   StrnCpy (EncodedPassword, Password, StrLen (Password));\r
189   EncodePassword (EncodedPassword, StrLen (EncodedPassword) * sizeof (CHAR16));\r
190   if (CompareMem (EncodedPassword, PrivateData->Configuration.WhatIsThePassword2, StrLen (EncodedPassword) * sizeof (CHAR16)) != 0) {\r
191     //\r
192     // Old password mismatch, return EFI_NOT_READY to prompt for error message\r
193     //\r
194     Status = EFI_NOT_READY;\r
195   } else {\r
196     Status = EFI_SUCCESS;\r
197   }\r
198 \r
199   FreePool (Password);\r
200   FreePool (EncodedPassword);\r
201 \r
202   return Status;\r
203 }\r
204 \r
205 /**\r
206   Encode the password using a simple algorithm.\r
207 \r
208   @param PrivateData This driver's private context data.\r
209   @param StringId    The password from User.\r
210 \r
211   @retval  EFI_SUCESS The operation is successful.\r
212   @return  Other value if gRT->SetVariable () fails.\r
213 \r
214 **/\r
215 EFI_STATUS\r
216 SetPassword (\r
217   IN DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData,\r
218   IN EFI_STRING_ID                   StringId\r
219   )\r
220 {\r
221   EFI_STATUS                      Status;\r
222   CHAR16                          *Password;\r
223   CHAR16                          *TempPassword;\r
224   UINTN                           PasswordSize;\r
225   DRIVER_SAMPLE_CONFIGURATION     *Configuration;\r
226   UINTN                           BufferSize;\r
227 \r
228   //\r
229   // Get Buffer Storage data from EFI variable\r
230   //\r
231   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
232   Status = gRT->GetVariable (\r
233                   VariableName,\r
234                   &mFormSetGuid,\r
235                   NULL,\r
236                   &BufferSize,\r
237                   &PrivateData->Configuration\r
238                   );\r
239   if (EFI_ERROR (Status)) {\r
240     return Status;\r
241   }\r
242 \r
243   //\r
244   // Get user input password\r
245   //\r
246   Password = &PrivateData->Configuration.WhatIsThePassword2[0];\r
247   PasswordSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);\r
248   ZeroMem (Password, PasswordSize);\r
249 \r
250   TempPassword = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);\r
251   if (TempPassword == NULL) {\r
252     return EFI_NOT_READY;\r
253   }\r
254   if (StrSize (TempPassword) > PasswordSize) {\r
255     FreePool (TempPassword);\r
256     return EFI_NOT_READY;\r
257   }\r
258   StrnCpy (Password, TempPassword, StrLen (TempPassword));\r
259   FreePool (TempPassword);\r
260 \r
261   //\r
262   // Retrive uncommitted data from Browser\r
263   //\r
264   Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));\r
265   ASSERT (Configuration != NULL);\r
266   if (HiiGetBrowserData (&mFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {\r
267     //\r
268     // Update password's clear text in the screen\r
269     //\r
270     CopyMem (Configuration->PasswordClearText, Password, StrSize (Password));\r
271 \r
272     //\r
273     // Update uncommitted data of Browser\r
274     //\r
275     HiiSetBrowserData (\r
276        &mFormSetGuid,\r
277        VariableName,\r
278        sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
279        (UINT8 *) Configuration,\r
280        NULL\r
281        );\r
282   }\r
283 \r
284   //\r
285   // Free Configuration Buffer\r
286   //\r
287   FreePool (Configuration);\r
288 \r
289 \r
290   //\r
291   // Set password\r
292   //\r
293   EncodePassword (Password, StrLen (Password) * 2);\r
294   Status = gRT->SetVariable(\r
295                   VariableName,\r
296                   &mFormSetGuid,\r
297                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
298                   sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
299                   &PrivateData->Configuration\r
300                   );\r
301   return Status;\r
302 }\r
303 \r
304 /**\r
305  Update names of Name/Value storage to current language.\r
306 \r
307  @param PrivateData   Points to the driver private data.\r
308 \r
309  @retval EFI_SUCCESS   All names are successfully updated.\r
310  @retval EFI_NOT_FOUND Failed to get Name from HII database.\r
311 \r
312 **/\r
313 EFI_STATUS\r
314 LoadNameValueNames (\r
315   IN DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData\r
316   )\r
317 {\r
318   UINTN      Index;\r
319 \r
320   //\r
321   // Get Name/Value name string of current language\r
322   //\r
323   for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {\r
324     PrivateData->NameValueName[Index] = HiiGetString (\r
325                                          PrivateData->HiiHandle[0],\r
326                                          PrivateData->NameStringId[Index],\r
327                                          NULL\r
328                                          );\r
329     if (PrivateData->NameValueName[Index] == NULL) {\r
330       return EFI_NOT_FOUND;\r
331     }\r
332   }\r
333 \r
334   return EFI_SUCCESS;\r
335 }\r
336 \r
337 /**\r
338   This function allows a caller to extract the current configuration for one\r
339   or more named elements from the target driver.\r
340 \r
341   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
342   @param  Request                A null-terminated Unicode string in\r
343                                  <ConfigRequest> format.\r
344   @param  Progress               On return, points to a character in the Request\r
345                                  string. Points to the string's null terminator if\r
346                                  request was successful. Points to the most recent\r
347                                  '&' before the first failing name/value pair (or\r
348                                  the beginning of the string if the failure is in\r
349                                  the first name/value pair) if the request was not\r
350                                  successful.\r
351   @param  Results                A null-terminated Unicode string in\r
352                                  <ConfigAltResp> format which has all values filled\r
353                                  in for the names in the Request string. String to\r
354                                  be allocated by the called function.\r
355 \r
356   @retval EFI_SUCCESS            The Results is filled with the requested values.\r
357   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
358   @retval EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown name.\r
359   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
360                                  driver.\r
361 \r
362 **/\r
363 EFI_STATUS\r
364 EFIAPI\r
365 ExtractConfig (\r
366   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
367   IN  CONST EFI_STRING                       Request,\r
368   OUT EFI_STRING                             *Progress,\r
369   OUT EFI_STRING                             *Results\r
370   )\r
371 {\r
372   EFI_STATUS                       Status;\r
373   UINTN                            BufferSize;\r
374   DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;\r
375   EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
376   EFI_STRING                       ConfigRequest;\r
377   EFI_STRING                       ConfigRequestHdr;\r
378   UINTN                            Size;\r
379   EFI_STRING                       Value;\r
380   UINTN                            ValueStrLen;\r
381   CHAR16                           BackupChar;\r
382   CHAR16                           *StrPointer;\r
383   BOOLEAN                          AllocatedRequest;\r
384 \r
385   if (Progress == NULL || Results == NULL) {\r
386     return EFI_INVALID_PARAMETER;\r
387   }\r
388   //\r
389   // Initialize the local variables.\r
390   //\r
391   ConfigRequestHdr  = NULL;\r
392   ConfigRequest     = NULL;\r
393   Size              = 0;\r
394   *Progress         = Request;\r
395   AllocatedRequest  = FALSE;\r
396 \r
397   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
398   HiiConfigRouting = PrivateData->HiiConfigRouting;\r
399 \r
400   //\r
401   // Get Buffer Storage data from EFI variable.\r
402   // Try to get the current setting from variable.\r
403   //\r
404   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
405   Status = gRT->GetVariable (\r
406             VariableName,\r
407             &mFormSetGuid,\r
408             NULL,\r
409             &BufferSize,\r
410             &PrivateData->Configuration\r
411             );\r
412   if (EFI_ERROR (Status)) {\r
413     return EFI_NOT_FOUND;\r
414   }\r
415 \r
416   if (Request == NULL) {\r
417     //\r
418     // Request is set to NULL, construct full request string.\r
419     //\r
420 \r
421     //\r
422     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
423     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
424     //\r
425     ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, PrivateData->DriverHandle[0]);\r
426     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
427     ConfigRequest = AllocateZeroPool (Size);\r
428     AllocatedRequest = TRUE;\r
429     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
430     FreePool (ConfigRequestHdr);\r
431   } else {\r
432     //\r
433     // Check routing data in <ConfigHdr>.\r
434     // Note: if only one Storage is used, then this checking could be skipped.\r
435     //\r
436     if (!HiiIsConfigHdrMatch (Request, &mFormSetGuid, NULL)) {\r
437       return EFI_NOT_FOUND;\r
438     }\r
439     //\r
440     // Set Request to the unified request string.\r
441     //\r
442     ConfigRequest = Request;\r
443     //\r
444     // Check whether Request includes Request Element.\r
445     //\r
446     if (StrStr (Request, L"OFFSET") == NULL) {\r
447       //\r
448       // Check Request Element does exist in Reques String\r
449       //\r
450       StrPointer = StrStr (Request, L"PATH");\r
451       if (StrPointer == NULL) {\r
452         return EFI_INVALID_PARAMETER;\r
453       }\r
454       if (StrStr (StrPointer, L"&") == NULL) {\r
455         Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);\r
456         ConfigRequest    = AllocateZeroPool (Size);\r
457         AllocatedRequest = TRUE;\r
458         UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", Request, (UINT64)BufferSize);\r
459       }\r
460     }\r
461   }\r
462 \r
463   //\r
464   // Check if requesting Name/Value storage\r
465   //\r
466   if (StrStr (ConfigRequest, L"OFFSET") == NULL) {\r
467     //\r
468     // Update Name/Value storage Names\r
469     //\r
470     Status = LoadNameValueNames (PrivateData);\r
471     if (EFI_ERROR (Status)) {\r
472       return Status;\r
473     }\r
474 \r
475     //\r
476     // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"\r
477     // <Request>   ::=<ConfigHdr>&Name0&Name1&Name2\r
478     // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044\r
479     //\r
480     BufferSize = (StrLen (ConfigRequest) +\r
481       1 + sizeof (PrivateData->Configuration.NameValueVar0) * 2 +\r
482       1 + sizeof (PrivateData->Configuration.NameValueVar1) * 2 +\r
483       1 + sizeof (PrivateData->Configuration.NameValueVar2) * 2 + 1) * sizeof (CHAR16);\r
484     *Results = AllocateZeroPool (BufferSize);\r
485     ASSERT (*Results != NULL);\r
486     StrCpy (*Results, ConfigRequest);\r
487     Value = *Results;\r
488 \r
489     //\r
490     // Append value of NameValueVar0, type is UINT8\r
491     //\r
492     if ((Value = StrStr (*Results, PrivateData->NameValueName[0])) != NULL) {\r
493       Value += StrLen (PrivateData->NameValueName[0]);\r
494       ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar0) * 2) + 1);\r
495       CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
496 \r
497       BackupChar = Value[ValueStrLen];\r
498       *Value++   = L'=';\r
499       Value += UnicodeValueToString (\r
500                  Value, \r
501                  PREFIX_ZERO | RADIX_HEX, \r
502                  PrivateData->Configuration.NameValueVar0, \r
503                  sizeof (PrivateData->Configuration.NameValueVar0) * 2\r
504                  );\r
505       *Value = BackupChar;\r
506     }\r
507 \r
508     //\r
509     // Append value of NameValueVar1, type is UINT16\r
510     //\r
511     if ((Value = StrStr (*Results, PrivateData->NameValueName[1])) != NULL) {\r
512       Value += StrLen (PrivateData->NameValueName[1]);\r
513       ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar1) * 2) + 1);\r
514       CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
515 \r
516       BackupChar = Value[ValueStrLen];\r
517       *Value++   = L'=';\r
518       Value += UnicodeValueToString (\r
519                 Value, \r
520                 PREFIX_ZERO | RADIX_HEX, \r
521                 PrivateData->Configuration.NameValueVar1, \r
522                 sizeof (PrivateData->Configuration.NameValueVar1) * 2\r
523                 );\r
524       *Value = BackupChar;\r
525     }\r
526 \r
527     //\r
528     // Append value of NameValueVar2, type is CHAR16 *\r
529     //\r
530     if ((Value = StrStr (*Results, PrivateData->NameValueName[2])) != NULL) {\r
531       Value += StrLen (PrivateData->NameValueName[2]);\r
532       ValueStrLen = StrLen (PrivateData->Configuration.NameValueVar2) * 4 + 1;\r
533       CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
534 \r
535       *Value++ = L'=';\r
536       //\r
537       // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
538       //\r
539       StrPointer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;\r
540       for (; *StrPointer != L'\0'; StrPointer++) {\r
541         Value += UnicodeValueToString (Value, PREFIX_ZERO | RADIX_HEX, *StrPointer, 4);\r
542       }\r
543     }\r
544     \r
545     Status = EFI_SUCCESS;\r
546   } else {\r
547     //\r
548     // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
549     //\r
550     Status = HiiConfigRouting->BlockToConfig (\r
551                                   HiiConfigRouting,\r
552                                   ConfigRequest,\r
553                                   (UINT8 *) &PrivateData->Configuration,\r
554                                   BufferSize,\r
555                                   Results,\r
556                                   Progress\r
557                                   );\r
558   }\r
559 \r
560   //\r
561   // Free the allocated config request string.\r
562   //\r
563   if (AllocatedRequest) {\r
564     FreePool (ConfigRequest);\r
565   }\r
566   //\r
567   // Set Progress string to the original request string.\r
568   //\r
569   if (Request == NULL) {\r
570     *Progress = NULL;\r
571   } else if (StrStr (Request, L"OFFSET") == NULL) {\r
572     *Progress = Request + StrLen (Request);\r
573   }\r
574 \r
575   return Status;\r
576 }\r
577 \r
578 \r
579 /**\r
580   This function processes the results of changes in configuration.\r
581 \r
582   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
583   @param  Configuration          A null-terminated Unicode string in <ConfigResp>\r
584                                  format.\r
585   @param  Progress               A pointer to a string filled in with the offset of\r
586                                  the most recent '&' before the first failing\r
587                                  name/value pair (or the beginning of the string if\r
588                                  the failure is in the first name/value pair) or\r
589                                  the terminating NULL if all was successful.\r
590 \r
591   @retval EFI_SUCCESS            The Results is processed successfully.\r
592   @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
593   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
594                                  driver.\r
595 \r
596 **/\r
597 EFI_STATUS\r
598 EFIAPI\r
599 RouteConfig (\r
600   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
601   IN  CONST EFI_STRING                       Configuration,\r
602   OUT EFI_STRING                             *Progress\r
603   )\r
604 {\r
605   EFI_STATUS                       Status;\r
606   UINTN                            BufferSize;\r
607   DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;\r
608   EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
609   CHAR16                           *Value;\r
610   CHAR16                           *StrPtr;\r
611   CHAR16                           TemStr[5];\r
612   UINT8                            *DataBuffer;\r
613   UINT8                            DigitUint8;\r
614   UINTN                            Index;\r
615   CHAR16                           *StrBuffer;\r
616 \r
617   if (Configuration == NULL || Progress == NULL) {\r
618     return EFI_INVALID_PARAMETER;\r
619   }\r
620 \r
621   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
622   HiiConfigRouting = PrivateData->HiiConfigRouting;\r
623   *Progress = Configuration;\r
624 \r
625   //\r
626   // Check routing data in <ConfigHdr>.\r
627   // Note: if only one Storage is used, then this checking could be skipped.\r
628   //\r
629   if (!HiiIsConfigHdrMatch (Configuration, &mFormSetGuid, NULL)) {\r
630     return EFI_NOT_FOUND;\r
631   }\r
632 \r
633   //\r
634   // Get Buffer Storage data from EFI variable\r
635   //\r
636   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
637   Status = gRT->GetVariable (\r
638             VariableName,\r
639             &mFormSetGuid,\r
640             NULL,\r
641             &BufferSize,\r
642             &PrivateData->Configuration\r
643             );\r
644   if (EFI_ERROR (Status)) {\r
645     return Status;\r
646   }\r
647 \r
648   //\r
649   // Check if configuring Name/Value storage\r
650   //\r
651   if (StrStr (Configuration, L"OFFSET") == NULL) {\r
652     //\r
653     // Update Name/Value storage Names\r
654     //\r
655     Status = LoadNameValueNames (PrivateData);\r
656     if (EFI_ERROR (Status)) {\r
657       return Status;\r
658     }\r
659 \r
660     //\r
661     // Convert value for NameValueVar0\r
662     //\r
663     if ((Value = StrStr (Configuration, PrivateData->NameValueName[0])) != NULL) {\r
664       //\r
665       // Skip "Name="\r
666       //\r
667       Value += StrLen (PrivateData->NameValueName[0]);\r
668       Value++;\r
669       //\r
670       // Get Value String\r
671       //\r
672       StrPtr = StrStr (Value, L"&");\r
673       if (StrPtr == NULL) {\r
674         StrPtr = Value + StrLen (Value);\r
675       }\r
676       //\r
677       // Convert Value to Buffer data\r
678       //\r
679       DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar0;\r
680       ZeroMem (TemStr, sizeof (TemStr));\r
681       for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {\r
682         TemStr[0] = *StrPtr;\r
683         DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
684         if ((Index & 1) == 0) {\r
685           DataBuffer [Index/2] = DigitUint8;\r
686         } else {\r
687           DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);\r
688         }\r
689       }\r
690     }\r
691 \r
692     //\r
693     // Convert value for NameValueVar1\r
694     //\r
695     if ((Value = StrStr (Configuration, PrivateData->NameValueName[1])) != NULL) {\r
696       //\r
697       // Skip "Name="\r
698       //\r
699       Value += StrLen (PrivateData->NameValueName[1]);\r
700       Value++;\r
701       //\r
702       // Get Value String\r
703       //\r
704       StrPtr = StrStr (Value, L"&");\r
705       if (StrPtr == NULL) {\r
706         StrPtr = Value + StrLen (Value);\r
707       }\r
708       //\r
709       // Convert Value to Buffer data\r
710       //\r
711       DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar1;\r
712       ZeroMem (TemStr, sizeof (TemStr));\r
713       for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {\r
714         TemStr[0] = *StrPtr;\r
715         DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
716         if ((Index & 1) == 0) {\r
717           DataBuffer [Index/2] = DigitUint8;\r
718         } else {\r
719           DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);\r
720         }\r
721       }\r
722     }\r
723 \r
724     //\r
725     // Convert value for NameValueVar2\r
726     //\r
727     if ((Value = StrStr (Configuration, PrivateData->NameValueName[2])) != NULL) {\r
728       //\r
729       // Skip "Name="\r
730       //\r
731       Value += StrLen (PrivateData->NameValueName[2]);\r
732       Value++;\r
733       //\r
734       // Get Value String\r
735       //\r
736       StrPtr = StrStr (Value, L"&");\r
737       if (StrPtr == NULL) {\r
738         StrPtr = Value + StrLen (Value);\r
739       }\r
740       //\r
741       // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
742       //\r
743       StrBuffer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;\r
744       ZeroMem (TemStr, sizeof (TemStr));\r
745       while (Value < StrPtr) {\r
746         StrnCpy (TemStr, Value, 4);\r
747         *(StrBuffer++) = (CHAR16) StrHexToUint64 (TemStr);\r
748         Value += 4;\r
749       }\r
750       *StrBuffer = L'\0';\r
751     }\r
752 \r
753     //\r
754     // Store Buffer Storage back to EFI variable\r
755     //\r
756     Status = gRT->SetVariable(\r
757       VariableName,\r
758       &mFormSetGuid,\r
759       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
760       sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
761       &PrivateData->Configuration\r
762       );\r
763 \r
764     return Status;\r
765   }\r
766 \r
767   //\r
768   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
769   //\r
770   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
771   Status = HiiConfigRouting->ConfigToBlock (\r
772                                HiiConfigRouting,\r
773                                Configuration,\r
774                                (UINT8 *) &PrivateData->Configuration,\r
775                                &BufferSize,\r
776                                Progress\r
777                                );\r
778   if (EFI_ERROR (Status)) {\r
779     return Status;\r
780   }\r
781 \r
782   //\r
783   // Store Buffer Storage back to EFI variable\r
784   //\r
785   Status = gRT->SetVariable(\r
786                   VariableName,\r
787                   &mFormSetGuid,\r
788                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
789                   sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
790                   &PrivateData->Configuration\r
791                   );\r
792 \r
793   return Status;\r
794 }\r
795 \r
796 \r
797 /**\r
798   This function processes the results of changes in configuration.\r
799 \r
800   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
801   @param  Action                 Specifies the type of action taken by the browser.\r
802   @param  QuestionId             A unique value which is sent to the original\r
803                                  exporting driver so that it can identify the type\r
804                                  of data to expect.\r
805   @param  Type                   The type of value for the question.\r
806   @param  Value                  A pointer to the data being sent to the original\r
807                                  exporting driver.\r
808   @param  ActionRequest          On return, points to the action requested by the\r
809                                  callback function.\r
810 \r
811   @retval EFI_SUCCESS            The callback successfully handled the action.\r
812   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
813                                  variable and its data.\r
814   @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
815   @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
816                                  callback.\r
817 \r
818 **/\r
819 EFI_STATUS\r
820 EFIAPI\r
821 DriverCallback (\r
822   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
823   IN  EFI_BROWSER_ACTION                     Action,\r
824   IN  EFI_QUESTION_ID                        QuestionId,\r
825   IN  UINT8                                  Type,\r
826   IN  EFI_IFR_TYPE_VALUE                     *Value,\r
827   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
828   )\r
829 {\r
830   DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData;\r
831   EFI_STATUS                      Status;\r
832   UINT8                           MyVar;\r
833   VOID                            *StartOpCodeHandle;\r
834   VOID                            *OptionsOpCodeHandle;\r
835   EFI_IFR_GUID_LABEL              *StartLabel;\r
836   VOID                            *EndOpCodeHandle;\r
837   EFI_IFR_GUID_LABEL              *EndLabel;\r
838   EFI_INPUT_KEY                   Key;\r
839   DRIVER_SAMPLE_CONFIGURATION     *Configuration;\r
840   UINTN                           MyVarSize;\r
841 \r
842   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
843     //\r
844     // On FORM_OPEN event, update the form on-the-fly\r
845     //\r
846     PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
847 \r
848     //\r
849     // Initialize the container for dynamic opcodes\r
850     //\r
851     StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
852     ASSERT (StartOpCodeHandle != NULL);\r
853 \r
854     //\r
855     // Create Hii Extend Label OpCode as the start opcode\r
856     //\r
857     StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
858     StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
859     StartLabel->Number       = LABEL_UPDATE2;\r
860 \r
861     HiiCreateActionOpCode (\r
862       StartOpCodeHandle,                // Container for dynamic created opcodes\r
863       0x1238,                           // Question ID\r
864       STRING_TOKEN(STR_SAVE_TEXT),      // Prompt text\r
865       STRING_TOKEN(STR_SAVE_TEXT),      // Help text\r
866       EFI_IFR_FLAG_CALLBACK,            // Question flag\r
867       0                                 // Action String ID\r
868     );\r
869 \r
870     HiiUpdateForm (\r
871       PrivateData->HiiHandle[0],  // HII handle\r
872       &mFormSetGuid,              // Formset GUID\r
873       0x3,                        // Form ID\r
874       StartOpCodeHandle,          // Label for where to insert opcodes\r
875       NULL                        // Insert data\r
876       );\r
877 \r
878     HiiFreeOpCodeHandle (StartOpCodeHandle);\r
879     return EFI_SUCCESS;\r
880   }\r
881 \r
882   if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {\r
883     //\r
884     // On FORM_CLOSE event, show up a pop-up\r
885     //\r
886     do {\r
887       CreatePopUp (\r
888         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
889         &Key,\r
890         L"",\r
891         L"You are going to leave the Form!",\r
892         L"Press ESC or ENTER to continue ...",\r
893         L"",\r
894         NULL\r
895         );\r
896     } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
897 \r
898     return EFI_SUCCESS;\r
899   }\r
900 \r
901   if ((Value == NULL) || (ActionRequest == NULL)) {\r
902     return EFI_INVALID_PARAMETER;\r
903   }\r
904 \r
905   if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0)) {\r
906     return EFI_INVALID_PARAMETER;\r
907   }\r
908 \r
909   Status = EFI_SUCCESS;\r
910   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
911 \r
912   switch (QuestionId) {\r
913   case 0x1234:\r
914     //\r
915     // Initialize the container for dynamic opcodes\r
916     //\r
917     StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
918     ASSERT (StartOpCodeHandle != NULL);\r
919 \r
920     EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
921     ASSERT (EndOpCodeHandle != NULL);\r
922 \r
923     //\r
924     // Create Hii Extend Label OpCode as the start opcode\r
925     //\r
926     StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
927     StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
928     StartLabel->Number       = LABEL_UPDATE1;\r
929 \r
930     //\r
931     // Create Hii Extend Label OpCode as the end opcode\r
932     //\r
933     EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
934     EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
935     EndLabel->Number       = LABEL_END;\r
936 \r
937     HiiCreateActionOpCode (\r
938       StartOpCodeHandle,                // Container for dynamic created opcodes\r
939       0x1237,                           // Question ID\r
940       STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text\r
941       STRING_TOKEN(STR_EXIT_TEXT),      // Help text\r
942       EFI_IFR_FLAG_CALLBACK,            // Question flag\r
943       0                                 // Action String ID\r
944     );\r
945 \r
946     //\r
947     // Create Option OpCode\r
948     //\r
949     OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();\r
950     ASSERT (OptionsOpCodeHandle != NULL);\r
951 \r
952     HiiCreateOneOfOptionOpCode (\r
953       OptionsOpCodeHandle,\r
954       STRING_TOKEN (STR_BOOT_OPTION1),\r
955       0,\r
956       EFI_IFR_NUMERIC_SIZE_1,\r
957       1\r
958       );\r
959 \r
960     HiiCreateOneOfOptionOpCode (\r
961       OptionsOpCodeHandle,\r
962       STRING_TOKEN (STR_BOOT_OPTION2),\r
963       0,\r
964       EFI_IFR_NUMERIC_SIZE_1,\r
965       2\r
966       );\r
967 \r
968     //\r
969     // Prepare initial value for the dynamic created oneof Question\r
970     //\r
971     PrivateData->Configuration.DynamicOneof = 2;\r
972     Status = gRT->SetVariable(\r
973                     VariableName,\r
974                     &mFormSetGuid,\r
975                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
976                     sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
977                     &PrivateData->Configuration\r
978                     );\r
979 \r
980     //\r
981     // Set initial vlaue of dynamic created oneof Question in Form Browser\r
982     //\r
983     Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));\r
984     ASSERT (Configuration != NULL);\r
985     if (HiiGetBrowserData (&mFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {\r
986       Configuration->DynamicOneof = 2;\r
987 \r
988       //\r
989       // Update uncommitted data of Browser\r
990       //\r
991       HiiSetBrowserData (\r
992         &mFormSetGuid,\r
993         VariableName,\r
994         sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
995         (UINT8 *) Configuration,\r
996         NULL\r
997         );\r
998     }\r
999     FreePool (Configuration);\r
1000 \r
1001     HiiCreateOneOfOpCode (\r
1002       StartOpCodeHandle,                         // Container for dynamic created opcodes\r
1003       0x8001,                                    // Question ID (or call it "key")\r
1004       CONFIGURATION_VARSTORE_ID,                 // VarStore ID\r
1005       (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET,        // Offset in Buffer Storage\r
1006       STRING_TOKEN (STR_ONE_OF_PROMPT),          // Question prompt text\r
1007       STRING_TOKEN (STR_ONE_OF_HELP),            // Question help text\r
1008       EFI_IFR_FLAG_CALLBACK,                     // Question flag\r
1009       EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question Value\r
1010       OptionsOpCodeHandle,                       // Option Opcode list\r
1011       NULL                                       // Default Opcode is NULl\r
1012       );\r
1013 \r
1014     HiiCreateOrderedListOpCode (\r
1015       StartOpCodeHandle,                         // Container for dynamic created opcodes\r
1016       0x8002,                                    // Question ID\r
1017       CONFIGURATION_VARSTORE_ID,                 // VarStore ID\r
1018       (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET,  // Offset in Buffer Storage\r
1019       STRING_TOKEN (STR_BOOT_OPTIONS),           // Question prompt text\r
1020       STRING_TOKEN (STR_BOOT_OPTIONS),           // Question help text\r
1021       EFI_IFR_FLAG_RESET_REQUIRED,               // Question flag\r
1022       0,                                         // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET\r
1023       EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question value\r
1024       5,                                         // Maximum container\r
1025       OptionsOpCodeHandle,                       // Option Opcode list\r
1026       NULL                                       // Default Opcode is NULl\r
1027       );\r
1028 \r
1029     HiiCreateGotoOpCode (\r
1030       StartOpCodeHandle,                // Container for dynamic created opcodes\r
1031       1,                                // Target Form ID\r
1032       STRING_TOKEN (STR_GOTO_FORM1),    // Prompt text\r
1033       STRING_TOKEN (STR_GOTO_HELP),     // Help text\r
1034       0,                                // Question flag\r
1035       0x8003                            // Question ID\r
1036       );\r
1037 \r
1038     HiiUpdateForm (\r
1039       PrivateData->HiiHandle[0],  // HII handle\r
1040       &mFormSetGuid,              // Formset GUID\r
1041       0x1234,                     // Form ID\r
1042       StartOpCodeHandle,          // Label for where to insert opcodes\r
1043       EndOpCodeHandle             // Replace data\r
1044       );\r
1045 \r
1046     HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1047     HiiFreeOpCodeHandle (OptionsOpCodeHandle);\r
1048     HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1049     break;\r
1050 \r
1051   case 0x5678:\r
1052     //\r
1053     // We will reach here once the Question is refreshed\r
1054     //\r
1055 \r
1056     //\r
1057     // Initialize the container for dynamic opcodes\r
1058     //\r
1059     StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1060     ASSERT (StartOpCodeHandle != NULL);\r
1061 \r
1062     //\r
1063     // Create Hii Extend Label OpCode as the start opcode\r
1064     //\r
1065     StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1066     StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1067     StartLabel->Number       = LABEL_UPDATE2;\r
1068 \r
1069     HiiCreateActionOpCode (\r
1070       StartOpCodeHandle,                // Container for dynamic created opcodes\r
1071       0x1237,                           // Question ID\r
1072       STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text\r
1073       STRING_TOKEN(STR_EXIT_TEXT),      // Help text\r
1074       EFI_IFR_FLAG_CALLBACK,            // Question flag\r
1075       0                                 // Action String ID\r
1076     );\r
1077 \r
1078     HiiUpdateForm (\r
1079       PrivateData->HiiHandle[0],  // HII handle\r
1080       &mFormSetGuid,              // Formset GUID\r
1081       0x3,                        // Form ID\r
1082       StartOpCodeHandle,          // Label for where to insert opcodes\r
1083       NULL                        // Insert data\r
1084       );\r
1085 \r
1086     HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1087 \r
1088     //\r
1089     // Refresh the Question value\r
1090     //\r
1091     PrivateData->Configuration.DynamicRefresh++;\r
1092     Status = gRT->SetVariable(\r
1093                     VariableName,\r
1094                     &mFormSetGuid,\r
1095                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1096                     sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
1097                     &PrivateData->Configuration\r
1098                     );\r
1099 \r
1100     //\r
1101     // Change an EFI Variable storage (MyEfiVar) asynchronous, this will cause\r
1102     // the first statement in Form 3 be suppressed\r
1103     //\r
1104     MyVarSize = 1;\r
1105     MyVar = 111;\r
1106     Status = gRT->SetVariable(\r
1107                     L"MyVar",\r
1108                     &mFormSetGuid,\r
1109                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1110                     MyVarSize,\r
1111                     &MyVar\r
1112                     );\r
1113     break;\r
1114 \r
1115   case 0x1237:\r
1116     //\r
1117     // User press "Exit now", request Browser to exit\r
1118     //\r
1119     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
1120     break;\r
1121 \r
1122   case 0x1238:\r
1123     //\r
1124     // User press "Save now", request Browser to save the uncommitted data.\r
1125     //\r
1126     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1127     break;\r
1128 \r
1129   case 0x2000:\r
1130     //\r
1131     // When try to set a new password, user will be chanlleged with old password.\r
1132     // The Callback is responsible for validating old password input by user,\r
1133     // If Callback return EFI_SUCCESS, it indicates validation pass.\r
1134     //\r
1135     switch (PrivateData->PasswordState) {\r
1136     case BROWSER_STATE_VALIDATE_PASSWORD:\r
1137       Status = ValidatePassword (PrivateData, Value->string);\r
1138       if (Status == EFI_SUCCESS) {\r
1139         PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;\r
1140       }\r
1141       break;\r
1142 \r
1143     case BROWSER_STATE_SET_PASSWORD:\r
1144       Status = SetPassword (PrivateData, Value->string);\r
1145       PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
1146       break;\r
1147 \r
1148     default:\r
1149       break;\r
1150     }\r
1151 \r
1152     break;\r
1153 \r
1154   case 0x1111:\r
1155     //\r
1156     // EfiVarstore question takes sample action (print value as debug information) \r
1157     // after read/write question.\r
1158     //\r
1159     MyVarSize = 1;\r
1160     Status = gRT->GetVariable(\r
1161                     L"MyVar",\r
1162                     &mFormSetGuid,\r
1163                     NULL,\r
1164                     &MyVarSize,\r
1165                     &MyVar\r
1166                     );\r
1167     ASSERT_EFI_ERROR (Status);\r
1168     DEBUG ((DEBUG_INFO, "EfiVarstore question: Tall value is %d with value width %d\n", MyVar, MyVarSize));\r
1169   default:\r
1170     break;\r
1171   }\r
1172 \r
1173   return Status;\r
1174 }\r
1175 \r
1176 /**\r
1177   Main entry for this driver.\r
1178 \r
1179   @param ImageHandle     Image handle this driver.\r
1180   @param SystemTable     Pointer to SystemTable.\r
1181 \r
1182   @retval EFI_SUCESS     This function always complete successfully.\r
1183 \r
1184 **/\r
1185 EFI_STATUS\r
1186 EFIAPI\r
1187 DriverSampleInit (\r
1188   IN EFI_HANDLE                   ImageHandle,\r
1189   IN EFI_SYSTEM_TABLE             *SystemTable\r
1190   )\r
1191 {\r
1192   EFI_STATUS                      Status;\r
1193   EFI_HII_HANDLE                  HiiHandle[2];\r
1194   EFI_SCREEN_DESCRIPTOR           Screen;\r
1195   EFI_HII_DATABASE_PROTOCOL       *HiiDatabase;\r
1196   EFI_HII_STRING_PROTOCOL         *HiiString;\r
1197   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;\r
1198   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
1199   CHAR16                          *NewString;\r
1200   UINTN                           BufferSize;\r
1201   DRIVER_SAMPLE_CONFIGURATION     *Configuration;\r
1202   BOOLEAN                         ActionFlag;\r
1203   EFI_STRING                      ConfigRequestHdr;\r
1204 \r
1205   //\r
1206   // Initialize the local variables.\r
1207   //\r
1208   ConfigRequestHdr = NULL;\r
1209   //\r
1210   // Initialize screen dimensions for SendForm().\r
1211   // Remove 3 characters from top and bottom\r
1212   //\r
1213   ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
1214   gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);\r
1215 \r
1216   Screen.TopRow     = 3;\r
1217   Screen.BottomRow  = Screen.BottomRow - 3;\r
1218 \r
1219   //\r
1220   // Initialize driver private data\r
1221   //\r
1222   PrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));\r
1223   if (PrivateData == NULL) {\r
1224     return EFI_OUT_OF_RESOURCES;\r
1225   }\r
1226 \r
1227   PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;\r
1228 \r
1229   PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;\r
1230   PrivateData->ConfigAccess.RouteConfig = RouteConfig;\r
1231   PrivateData->ConfigAccess.Callback = DriverCallback;\r
1232   PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
1233 \r
1234   //\r
1235   // Locate Hii Database protocol\r
1236   //\r
1237   Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);\r
1238   if (EFI_ERROR (Status)) {\r
1239     return Status;\r
1240   }\r
1241   PrivateData->HiiDatabase = HiiDatabase;\r
1242 \r
1243   //\r
1244   // Locate HiiString protocol\r
1245   //\r
1246   Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);\r
1247   if (EFI_ERROR (Status)) {\r
1248     return Status;\r
1249   }\r
1250   PrivateData->HiiString = HiiString;\r
1251 \r
1252   //\r
1253   // Locate Formbrowser2 protocol\r
1254   //\r
1255   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
1256   if (EFI_ERROR (Status)) {\r
1257     return Status;\r
1258   }\r
1259   PrivateData->FormBrowser2 = FormBrowser2;\r
1260 \r
1261   //\r
1262   // Locate ConfigRouting protocol\r
1263   //\r
1264   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
1265   if (EFI_ERROR (Status)) {\r
1266     return Status;\r
1267   }\r
1268   PrivateData->HiiConfigRouting = HiiConfigRouting;\r
1269 \r
1270   Status = gBS->InstallMultipleProtocolInterfaces (\r
1271                   &DriverHandle[0],\r
1272                   &gEfiDevicePathProtocolGuid,\r
1273                   &mHiiVendorDevicePath0,\r
1274                   &gEfiHiiConfigAccessProtocolGuid,\r
1275                   &PrivateData->ConfigAccess,\r
1276                   NULL\r
1277                   );\r
1278   ASSERT_EFI_ERROR (Status);\r
1279 \r
1280   PrivateData->DriverHandle[0] = DriverHandle[0];\r
1281 \r
1282   //\r
1283   // Publish our HII data\r
1284   //\r
1285   HiiHandle[0] = HiiAddPackages (\r
1286                    &mFormSetGuid,\r
1287                    DriverHandle[0],\r
1288                    DriverSampleStrings,\r
1289                    VfrBin,\r
1290                    NULL\r
1291                    );\r
1292   if (HiiHandle[0] == NULL) {\r
1293     return EFI_OUT_OF_RESOURCES;\r
1294   }\r
1295 \r
1296   PrivateData->HiiHandle[0] = HiiHandle[0];\r
1297 \r
1298   //\r
1299   // Publish another Fromset\r
1300   //\r
1301   Status = gBS->InstallMultipleProtocolInterfaces (\r
1302                   &DriverHandle[1],\r
1303                   &gEfiDevicePathProtocolGuid,\r
1304                   &mHiiVendorDevicePath1,\r
1305                   NULL\r
1306                   );\r
1307   ASSERT_EFI_ERROR (Status);\r
1308 \r
1309   PrivateData->DriverHandle[1] = DriverHandle[1];\r
1310 \r
1311   HiiHandle[1] = HiiAddPackages (\r
1312                    &mInventoryGuid,\r
1313                    DriverHandle[1],\r
1314                    DriverSampleStrings,\r
1315                    InventoryBin,\r
1316                    NULL\r
1317                    );\r
1318   if (HiiHandle[1] == NULL) {\r
1319     DriverSampleUnload (ImageHandle);\r
1320     return EFI_OUT_OF_RESOURCES;\r
1321   }\r
1322 \r
1323   PrivateData->HiiHandle[1] = HiiHandle[1];\r
1324 \r
1325   //\r
1326   // Very simple example of how one would update a string that is already\r
1327   // in the HII database\r
1328   //\r
1329   NewString = L"700 Mhz";\r
1330 \r
1331   if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {\r
1332     DriverSampleUnload (ImageHandle);\r
1333     return EFI_OUT_OF_RESOURCES;\r
1334   }\r
1335 \r
1336   HiiSetString (HiiHandle[0], 0, NewString, NULL);\r
1337 \r
1338   //\r
1339   // Initialize Name/Value name String ID\r
1340   //\r
1341   PrivateData->NameStringId[0] = STR_NAME_VALUE_VAR_NAME0;\r
1342   PrivateData->NameStringId[1] = STR_NAME_VALUE_VAR_NAME1;\r
1343   PrivateData->NameStringId[2] = STR_NAME_VALUE_VAR_NAME2;\r
1344 \r
1345   //\r
1346   // Initialize configuration data\r
1347   //\r
1348   Configuration = &PrivateData->Configuration;\r
1349   ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));\r
1350 \r
1351   //\r
1352   // Try to read NV config EFI variable first\r
1353   //\r
1354   ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, DriverHandle[0]);\r
1355   ASSERT (ConfigRequestHdr != NULL);\r
1356 \r
1357   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
1358   Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);\r
1359   if (EFI_ERROR (Status)) {\r
1360     //\r
1361     // Store zero data Buffer Storage to EFI variable\r
1362     //\r
1363     Status = gRT->SetVariable(\r
1364                     VariableName,\r
1365                     &mFormSetGuid,\r
1366                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1367                     sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
1368                     Configuration\r
1369                     );\r
1370     ASSERT (Status == EFI_SUCCESS);\r
1371     //\r
1372     // EFI variable for NV config doesn't exit, we should build this variable\r
1373     // based on default values stored in IFR\r
1374     //\r
1375     ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);\r
1376     ASSERT (ActionFlag);\r
1377   } else {\r
1378     //\r
1379     // EFI variable does exist and Validate Current Setting\r
1380     //\r
1381     ActionFlag = HiiValidateSettings (ConfigRequestHdr);\r
1382     ASSERT (ActionFlag);\r
1383   }\r
1384 \r
1385   FreePool (ConfigRequestHdr);\r
1386 \r
1387 \r
1388   //\r
1389   // In default, this driver is built into Flash device image,\r
1390   // the following code doesn't run.\r
1391   //\r
1392 \r
1393   //\r
1394   // Example of how to display only the item we sent to HII\r
1395   // When this driver is not built into Flash device image,\r
1396   // it need to call SendForm to show front page by itself.\r
1397   //\r
1398   if (DISPLAY_ONLY_MY_ITEM <= 1) {\r
1399     //\r
1400     // Have the browser pull out our copy of the data, and only display our data\r
1401     //\r
1402     Status = FormBrowser2->SendForm (\r
1403                              FormBrowser2,\r
1404                              &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),\r
1405                              1,\r
1406                              NULL,\r
1407                              0,\r
1408                              NULL,\r
1409                              NULL\r
1410                              );\r
1411 \r
1412     HiiRemovePackages (HiiHandle[0]);\r
1413 \r
1414     HiiRemovePackages (HiiHandle[1]);\r
1415   }\r
1416 \r
1417   return EFI_SUCCESS;\r
1418 }\r
1419 \r
1420 /**\r
1421   Unloads the application and its installed protocol.\r
1422 \r
1423   @param[in]  ImageHandle       Handle that identifies the image to be unloaded.\r
1424 \r
1425   @retval EFI_SUCCESS           The image has been unloaded.\r
1426 **/\r
1427 EFI_STATUS\r
1428 EFIAPI\r
1429 DriverSampleUnload (\r
1430   IN EFI_HANDLE  ImageHandle\r
1431   )\r
1432 {\r
1433   UINTN Index;\r
1434   if (DriverHandle[0] != NULL) {\r
1435     gBS->UninstallMultipleProtocolInterfaces (\r
1436             DriverHandle[0],\r
1437             &gEfiDevicePathProtocolGuid,\r
1438             &mHiiVendorDevicePath0,\r
1439             &gEfiHiiConfigAccessProtocolGuid,\r
1440             &PrivateData->ConfigAccess,\r
1441             NULL\r
1442            );\r
1443     DriverHandle[0] = NULL;\r
1444   }\r
1445 \r
1446   if (DriverHandle[1] != NULL) {\r
1447     gBS->UninstallMultipleProtocolInterfaces (\r
1448             DriverHandle[1],\r
1449             &gEfiDevicePathProtocolGuid,\r
1450             &mHiiVendorDevicePath1,\r
1451             NULL\r
1452            );\r
1453     DriverHandle[1] = NULL;\r
1454   }\r
1455 \r
1456   if (PrivateData->HiiHandle[0] != NULL) {\r
1457     HiiRemovePackages (PrivateData->HiiHandle[0]);\r
1458   }\r
1459 \r
1460   if (PrivateData->HiiHandle[1] != NULL) {\r
1461     HiiRemovePackages (PrivateData->HiiHandle[1]);\r
1462   }\r
1463 \r
1464   if (PrivateData != NULL) {\r
1465     for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {\r
1466       if (PrivateData->NameValueName[Index] != NULL) {\r
1467         FreePool (PrivateData->NameValueName[Index]);\r
1468       }\r
1469     }\r
1470     FreePool (PrivateData);\r
1471     PrivateData = NULL;\r
1472   }\r
1473 \r
1474   return EFI_SUCCESS;\r
1475 }\r