Add example of Name/Value pair var store to DriverSample
[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 - 2009, 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 \r
384 \r
385   if (Progress == NULL || Results == NULL || Request == 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 \r
396   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
397   HiiConfigRouting = PrivateData->HiiConfigRouting;\r
398 \r
399   //\r
400   // Get Buffer Storage data from EFI variable.\r
401   // Try to get the current setting from variable.\r
402   //\r
403   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
404   Status = gRT->GetVariable (\r
405             VariableName,\r
406             &mFormSetGuid,\r
407             NULL,\r
408             &BufferSize,\r
409             &PrivateData->Configuration\r
410             );\r
411   if (EFI_ERROR (Status)) {\r
412     return EFI_NOT_FOUND;\r
413   }\r
414 \r
415   if (Request == NULL) {\r
416     //\r
417     // Request is set to NULL, construct full request string.\r
418     //\r
419 \r
420     //\r
421     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
422     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
423     //\r
424     ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, PrivateData->DriverHandle[0]);\r
425     Size = (StrLen (ConfigRequest) + 32 + 1) * sizeof (CHAR16);\r
426     ConfigRequest = AllocateZeroPool (Size);\r
427     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
428     FreePool (ConfigRequestHdr);\r
429   } else {\r
430     //\r
431     // Check routing data in <ConfigHdr>.\r
432     // Note: if only one Storage is used, then this checking could be skipped.\r
433     //\r
434     if (!HiiIsConfigHdrMatch (Request, &mFormSetGuid, NULL)) {\r
435       return EFI_NOT_FOUND;\r
436     }\r
437     ConfigRequest = Request;\r
438 \r
439     //\r
440     // Check if requesting Name/Value storage\r
441     //\r
442     if (StrStr (Request, L"OFFSET") == NULL) {\r
443       //\r
444       // Update Name/Value storage Names\r
445       //\r
446       Status = LoadNameValueNames (PrivateData);\r
447       if (EFI_ERROR (Status)) {\r
448         return Status;\r
449       }\r
450 \r
451       //\r
452       // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"\r
453       // <Request>   ::=<ConfigHdr>&Name0&Name1&Name2\r
454       // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044\r
455       //\r
456       BufferSize = (StrLen (Request) +\r
457         1 + sizeof (PrivateData->Configuration.NameValueVar0) * 2 +\r
458         1 + sizeof (PrivateData->Configuration.NameValueVar1) * 2 +\r
459         1 + sizeof (PrivateData->Configuration.NameValueVar2) * 2 + 1) * sizeof (CHAR16);\r
460       *Results = AllocateZeroPool (BufferSize);\r
461       ASSERT (*Results != NULL);\r
462       StrCpy (*Results, Request);\r
463       Value = *Results;\r
464 \r
465       //\r
466       // Append value of NameValueVar0, type is UINT8\r
467       //\r
468       if ((Value = StrStr (*Results, PrivateData->NameValueName[0])) != NULL) {\r
469         Value += StrLen (PrivateData->NameValueName[0]);\r
470         ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar0) * 2) + 1);\r
471         CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
472 \r
473         BackupChar = Value[ValueStrLen];\r
474         *Value++   = L'=';\r
475         Value += UnicodeValueToString (\r
476                    Value, \r
477                    PREFIX_ZERO | RADIX_HEX, \r
478                    PrivateData->Configuration.NameValueVar0, \r
479                    sizeof (PrivateData->Configuration.NameValueVar0) * 2\r
480                    );\r
481         *Value = BackupChar;\r
482       }\r
483 \r
484       //\r
485       // Append value of NameValueVar1, type is UINT16\r
486       //\r
487       if ((Value = StrStr (*Results, PrivateData->NameValueName[1])) != NULL) {\r
488         Value += StrLen (PrivateData->NameValueName[1]);\r
489         ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar1) * 2) + 1);\r
490         CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
491 \r
492         BackupChar = Value[ValueStrLen];\r
493         *Value++   = L'=';\r
494         Value += UnicodeValueToString (\r
495                   Value, \r
496                   PREFIX_ZERO | RADIX_HEX, \r
497                   PrivateData->Configuration.NameValueVar1, \r
498                   sizeof (PrivateData->Configuration.NameValueVar1) * 2\r
499                   );\r
500         *Value = BackupChar;\r
501       }\r
502 \r
503       //\r
504       // Append value of NameValueVar2, type is CHAR16 *\r
505       //\r
506       if ((Value = StrStr (*Results, PrivateData->NameValueName[2])) != NULL) {\r
507         Value += StrLen (PrivateData->NameValueName[2]);\r
508         ValueStrLen = StrLen (PrivateData->Configuration.NameValueVar2) * 4 + 1;\r
509         CopyMem (Value + ValueStrLen, Value, StrSize (Value));\r
510 \r
511         *Value++ = L'=';\r
512         //\r
513         // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
514         //\r
515         StrPointer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;\r
516         for (; *StrPointer != L'\0'; StrPointer++) {\r
517           Value += UnicodeValueToString (Value, PREFIX_ZERO | RADIX_HEX, *StrPointer, 4);\r
518         }\r
519       }\r
520 \r
521       Progress = (EFI_STRING *) Request + StrLen (Request);\r
522       return EFI_SUCCESS;\r
523     }\r
524   }\r
525 \r
526   //\r
527   // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
528   //\r
529   Status = HiiConfigRouting->BlockToConfig (\r
530                                 HiiConfigRouting,\r
531                                 ConfigRequest,\r
532                                 (UINT8 *) &PrivateData->Configuration,\r
533                                 BufferSize,\r
534                                 Results,\r
535                                 Progress\r
536                                 );\r
537 \r
538   if (Request == NULL) {\r
539     FreePool (ConfigRequest);\r
540     *Progress = NULL;\r
541   }\r
542 \r
543   return Status;\r
544 }\r
545 \r
546 \r
547 /**\r
548   This function processes the results of changes in configuration.\r
549 \r
550   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
551   @param  Configuration          A null-terminated Unicode string in <ConfigResp>\r
552                                  format.\r
553   @param  Progress               A pointer to a string filled in with the offset of\r
554                                  the most recent '&' before the first failing\r
555                                  name/value pair (or the beginning of the string if\r
556                                  the failure is in the first name/value pair) or\r
557                                  the terminating NULL if all was successful.\r
558 \r
559   @retval EFI_SUCCESS            The Results is processed successfully.\r
560   @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
561   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
562                                  driver.\r
563 \r
564 **/\r
565 EFI_STATUS\r
566 EFIAPI\r
567 RouteConfig (\r
568   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
569   IN  CONST EFI_STRING                       Configuration,\r
570   OUT EFI_STRING                             *Progress\r
571   )\r
572 {\r
573   EFI_STATUS                       Status;\r
574   UINTN                            BufferSize;\r
575   DRIVER_SAMPLE_PRIVATE_DATA       *PrivateData;\r
576   EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
577   CHAR16                           *Value;\r
578   CHAR16                           *StrPtr;\r
579   CHAR16                           TemStr[5];\r
580   UINT8                            *DataBuffer;\r
581   UINT8                            DigitUint8;\r
582   UINTN                            Index;\r
583   CHAR16                           *StrBuffer;\r
584 \r
585   if (Configuration == NULL || Progress == NULL) {\r
586     return EFI_INVALID_PARAMETER;\r
587   }\r
588 \r
589   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
590   HiiConfigRouting = PrivateData->HiiConfigRouting;\r
591   *Progress = Configuration;\r
592 \r
593   //\r
594   // Check routing data in <ConfigHdr>.\r
595   // Note: if only one Storage is used, then this checking could be skipped.\r
596   //\r
597   if (!HiiIsConfigHdrMatch (Configuration, &mFormSetGuid, NULL)) {\r
598     return EFI_NOT_FOUND;\r
599   }\r
600 \r
601   //\r
602   // Get Buffer Storage data from EFI variable\r
603   //\r
604   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
605   Status = gRT->GetVariable (\r
606             VariableName,\r
607             &mFormSetGuid,\r
608             NULL,\r
609             &BufferSize,\r
610             &PrivateData->Configuration\r
611             );\r
612   if (EFI_ERROR (Status)) {\r
613     return Status;\r
614   }\r
615 \r
616   //\r
617   // Check if configuring Name/Value storage\r
618   //\r
619   if (StrStr (Configuration, L"OFFSET") == NULL) {\r
620     //\r
621     // Update Name/Value storage Names\r
622     //\r
623     Status = LoadNameValueNames (PrivateData);\r
624     if (EFI_ERROR (Status)) {\r
625       return Status;\r
626     }\r
627 \r
628     //\r
629     // Convert value for NameValueVar0\r
630     //\r
631     if ((Value = StrStr (Configuration, PrivateData->NameValueName[0])) != NULL) {\r
632       //\r
633       // Skip "Name="\r
634       //\r
635       Value += StrLen (PrivateData->NameValueName[0]);\r
636       Value++;\r
637       //\r
638       // Get Value String\r
639       //\r
640       StrPtr = StrStr (Value, L"&");\r
641       if (StrPtr == NULL) {\r
642         StrPtr = Value + StrLen (Value);\r
643       }\r
644       //\r
645       // Convert Value to Buffer data\r
646       //\r
647       DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar0;\r
648       ZeroMem (TemStr, sizeof (TemStr));\r
649       for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {\r
650         TemStr[0] = *StrPtr;\r
651         DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
652         if ((Index & 1) == 0) {\r
653           DataBuffer [Index/2] = DigitUint8;\r
654         } else {\r
655           DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);\r
656         }\r
657       }\r
658     }\r
659 \r
660     //\r
661     // Convert value for NameValueVar1\r
662     //\r
663     if ((Value = StrStr (Configuration, PrivateData->NameValueName[1])) != NULL) {\r
664       //\r
665       // Skip "Name="\r
666       //\r
667       Value += StrLen (PrivateData->NameValueName[1]);\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.NameValueVar1;\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 NameValueVar2\r
694     //\r
695     if ((Value = StrStr (Configuration, PrivateData->NameValueName[2])) != NULL) {\r
696       //\r
697       // Skip "Name="\r
698       //\r
699       Value += StrLen (PrivateData->NameValueName[2]);\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 Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
710       //\r
711       StrBuffer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;\r
712       ZeroMem (TemStr, sizeof (TemStr));\r
713       while (Value < StrPtr) {\r
714         StrnCpy (TemStr, Value, 4);\r
715         *(StrBuffer++) = (CHAR16) StrHexToUint64 (TemStr);\r
716         Value += 4;\r
717       }\r
718       *StrBuffer = L'\0';\r
719     }\r
720 \r
721     //\r
722     // Store Buffer Storage back to EFI variable\r
723     //\r
724     Status = gRT->SetVariable(\r
725       VariableName,\r
726       &mFormSetGuid,\r
727       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
728       sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
729       &PrivateData->Configuration\r
730       );\r
731 \r
732     return Status;\r
733   }\r
734 \r
735   //\r
736   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
737   //\r
738   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
739   Status = HiiConfigRouting->ConfigToBlock (\r
740                                HiiConfigRouting,\r
741                                Configuration,\r
742                                (UINT8 *) &PrivateData->Configuration,\r
743                                &BufferSize,\r
744                                Progress\r
745                                );\r
746   if (EFI_ERROR (Status)) {\r
747     return Status;\r
748   }\r
749 \r
750   //\r
751   // Store Buffer Storage back to EFI variable\r
752   //\r
753   Status = gRT->SetVariable(\r
754                   VariableName,\r
755                   &mFormSetGuid,\r
756                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
757                   sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
758                   &PrivateData->Configuration\r
759                   );\r
760 \r
761   return Status;\r
762 }\r
763 \r
764 \r
765 /**\r
766   This function processes the results of changes in configuration.\r
767 \r
768   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
769   @param  Action                 Specifies the type of action taken by the browser.\r
770   @param  QuestionId             A unique value which is sent to the original\r
771                                  exporting driver so that it can identify the type\r
772                                  of data to expect.\r
773   @param  Type                   The type of value for the question.\r
774   @param  Value                  A pointer to the data being sent to the original\r
775                                  exporting driver.\r
776   @param  ActionRequest          On return, points to the action requested by the\r
777                                  callback function.\r
778 \r
779   @retval EFI_SUCCESS            The callback successfully handled the action.\r
780   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
781                                  variable and its data.\r
782   @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
783   @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
784                                  callback.\r
785 \r
786 **/\r
787 EFI_STATUS\r
788 EFIAPI\r
789 DriverCallback (\r
790   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
791   IN  EFI_BROWSER_ACTION                     Action,\r
792   IN  EFI_QUESTION_ID                        QuestionId,\r
793   IN  UINT8                                  Type,\r
794   IN  EFI_IFR_TYPE_VALUE                     *Value,\r
795   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
796   )\r
797 {\r
798   DRIVER_SAMPLE_PRIVATE_DATA      *PrivateData;\r
799   EFI_STATUS                      Status;\r
800   UINT8                           MyVar;\r
801   VOID                            *StartOpCodeHandle;\r
802   VOID                            *OptionsOpCodeHandle;\r
803   EFI_IFR_GUID_LABEL              *StartLabel;\r
804   VOID                            *EndOpCodeHandle;\r
805   EFI_IFR_GUID_LABEL              *EndLabel;\r
806   EFI_INPUT_KEY                   Key;\r
807   DRIVER_SAMPLE_CONFIGURATION     *Configuration;\r
808   UINTN                           MyVarSize;\r
809 \r
810   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
811     //\r
812     // On FORM_OPEN event, update the form on-the-fly\r
813     //\r
814     PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
815 \r
816     //\r
817     // Initialize the container for dynamic opcodes\r
818     //\r
819     StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
820     ASSERT (StartOpCodeHandle != NULL);\r
821 \r
822     //\r
823     // Create Hii Extend Label OpCode as the start opcode\r
824     //\r
825     StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
826     StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
827     StartLabel->Number       = LABEL_UPDATE2;\r
828 \r
829     HiiCreateActionOpCode (\r
830       StartOpCodeHandle,                // Container for dynamic created opcodes\r
831       0x1238,                           // Question ID\r
832       STRING_TOKEN(STR_SAVE_TEXT),      // Prompt text\r
833       STRING_TOKEN(STR_SAVE_TEXT),      // Help text\r
834       EFI_IFR_FLAG_CALLBACK,            // Question flag\r
835       0                                 // Action String ID\r
836     );\r
837 \r
838     HiiUpdateForm (\r
839       PrivateData->HiiHandle[0],  // HII handle\r
840       &mFormSetGuid,              // Formset GUID\r
841       0x3,                        // Form ID\r
842       StartOpCodeHandle,          // Label for where to insert opcodes\r
843       NULL                        // Insert data\r
844       );\r
845 \r
846     HiiFreeOpCodeHandle (StartOpCodeHandle);\r
847     return EFI_SUCCESS;\r
848   }\r
849 \r
850   if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {\r
851     //\r
852     // On FORM_CLOSE event, show up a pop-up\r
853     //\r
854     do {\r
855       CreatePopUp (\r
856         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
857         &Key,\r
858         L"",\r
859         L"You are going to leave the Form!",\r
860         L"Press ESC or ENTER to continue ...",\r
861         L"",\r
862         NULL\r
863         );\r
864     } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
865 \r
866     return EFI_SUCCESS;\r
867   }\r
868 \r
869   if ((Value == NULL) || (ActionRequest == NULL)) {\r
870     return EFI_INVALID_PARAMETER;\r
871   }\r
872 \r
873   if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0)) {\r
874     return EFI_INVALID_PARAMETER;\r
875   }\r
876 \r
877   Status = EFI_SUCCESS;\r
878   PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
879 \r
880   switch (QuestionId) {\r
881   case 0x1234:\r
882     //\r
883     // Initialize the container for dynamic opcodes\r
884     //\r
885     StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
886     ASSERT (StartOpCodeHandle != NULL);\r
887 \r
888     EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
889     ASSERT (EndOpCodeHandle != NULL);\r
890 \r
891     //\r
892     // Create Hii Extend Label OpCode as the start opcode\r
893     //\r
894     StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
895     StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
896     StartLabel->Number       = LABEL_UPDATE1;\r
897 \r
898     //\r
899     // Create Hii Extend Label OpCode as the end opcode\r
900     //\r
901     EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
902     EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
903     EndLabel->Number       = LABEL_END;\r
904 \r
905     HiiCreateActionOpCode (\r
906       StartOpCodeHandle,                // Container for dynamic created opcodes\r
907       0x1237,                           // Question ID\r
908       STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text\r
909       STRING_TOKEN(STR_EXIT_TEXT),      // Help text\r
910       EFI_IFR_FLAG_CALLBACK,            // Question flag\r
911       0                                 // Action String ID\r
912     );\r
913 \r
914     //\r
915     // Create Option OpCode\r
916     //\r
917     OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();\r
918     ASSERT (OptionsOpCodeHandle != NULL);\r
919 \r
920     HiiCreateOneOfOptionOpCode (\r
921       OptionsOpCodeHandle,\r
922       STRING_TOKEN (STR_BOOT_OPTION1),\r
923       0,\r
924       EFI_IFR_NUMERIC_SIZE_1,\r
925       1\r
926       );\r
927 \r
928     HiiCreateOneOfOptionOpCode (\r
929       OptionsOpCodeHandle,\r
930       STRING_TOKEN (STR_BOOT_OPTION2),\r
931       0,\r
932       EFI_IFR_NUMERIC_SIZE_1,\r
933       2\r
934       );\r
935 \r
936     //\r
937     // Prepare initial value for the dynamic created oneof Question\r
938     //\r
939     PrivateData->Configuration.DynamicOneof = 2;\r
940     Status = gRT->SetVariable(\r
941                     VariableName,\r
942                     &mFormSetGuid,\r
943                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
944                     sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
945                     &PrivateData->Configuration\r
946                     );\r
947 \r
948     //\r
949     // Set initial vlaue of dynamic created oneof Question in Form Browser\r
950     //\r
951     Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));\r
952     ASSERT (Configuration != NULL);\r
953     if (HiiGetBrowserData (&mFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {\r
954       Configuration->DynamicOneof = 2;\r
955 \r
956       //\r
957       // Update uncommitted data of Browser\r
958       //\r
959       HiiSetBrowserData (\r
960         &mFormSetGuid,\r
961         VariableName,\r
962         sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
963         (UINT8 *) Configuration,\r
964         NULL\r
965         );\r
966     }\r
967     FreePool (Configuration);\r
968 \r
969     HiiCreateOneOfOpCode (\r
970       StartOpCodeHandle,                         // Container for dynamic created opcodes\r
971       0x8001,                                    // Question ID (or call it "key")\r
972       CONFIGURATION_VARSTORE_ID,                 // VarStore ID\r
973       (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET,        // Offset in Buffer Storage\r
974       STRING_TOKEN (STR_ONE_OF_PROMPT),          // Question prompt text\r
975       STRING_TOKEN (STR_ONE_OF_HELP),            // Question help text\r
976       EFI_IFR_FLAG_CALLBACK,                     // Question flag\r
977       EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question Value\r
978       OptionsOpCodeHandle,                       // Option Opcode list\r
979       NULL                                       // Default Opcode is NULl\r
980       );\r
981 \r
982     HiiCreateOrderedListOpCode (\r
983       StartOpCodeHandle,                         // Container for dynamic created opcodes\r
984       0x8002,                                    // Question ID\r
985       CONFIGURATION_VARSTORE_ID,                 // VarStore ID\r
986       (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET,  // Offset in Buffer Storage\r
987       STRING_TOKEN (STR_BOOT_OPTIONS),           // Question prompt text\r
988       STRING_TOKEN (STR_BOOT_OPTIONS),           // Question help text\r
989       EFI_IFR_FLAG_RESET_REQUIRED,               // Question flag\r
990       0,                                         // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET\r
991       EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question value\r
992       5,                                         // Maximum container\r
993       OptionsOpCodeHandle,                       // Option Opcode list\r
994       NULL                                       // Default Opcode is NULl\r
995       );\r
996 \r
997     HiiCreateGotoOpCode (\r
998       StartOpCodeHandle,                // Container for dynamic created opcodes\r
999       1,                                // Target Form ID\r
1000       STRING_TOKEN (STR_GOTO_FORM1),    // Prompt text\r
1001       STRING_TOKEN (STR_GOTO_HELP),     // Help text\r
1002       0,                                // Question flag\r
1003       0x8003                            // Question ID\r
1004       );\r
1005 \r
1006     HiiUpdateForm (\r
1007       PrivateData->HiiHandle[0],  // HII handle\r
1008       &mFormSetGuid,              // Formset GUID\r
1009       0x1234,                     // Form ID\r
1010       StartOpCodeHandle,          // Label for where to insert opcodes\r
1011       EndOpCodeHandle             // Replace data\r
1012       );\r
1013 \r
1014     HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1015     HiiFreeOpCodeHandle (OptionsOpCodeHandle);\r
1016     HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1017     break;\r
1018 \r
1019   case 0x5678:\r
1020     //\r
1021     // We will reach here once the Question is refreshed\r
1022     //\r
1023 \r
1024     //\r
1025     // Initialize the container for dynamic opcodes\r
1026     //\r
1027     StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1028     ASSERT (StartOpCodeHandle != NULL);\r
1029 \r
1030     //\r
1031     // Create Hii Extend Label OpCode as the start opcode\r
1032     //\r
1033     StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1034     StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1035     StartLabel->Number       = LABEL_UPDATE2;\r
1036 \r
1037     HiiCreateActionOpCode (\r
1038       StartOpCodeHandle,                // Container for dynamic created opcodes\r
1039       0x1237,                           // Question ID\r
1040       STRING_TOKEN(STR_EXIT_TEXT),      // Prompt text\r
1041       STRING_TOKEN(STR_EXIT_TEXT),      // Help text\r
1042       EFI_IFR_FLAG_CALLBACK,            // Question flag\r
1043       0                                 // Action String ID\r
1044     );\r
1045 \r
1046     HiiUpdateForm (\r
1047       PrivateData->HiiHandle[0],  // HII handle\r
1048       &mFormSetGuid,              // Formset GUID\r
1049       0x3,                        // Form ID\r
1050       StartOpCodeHandle,          // Label for where to insert opcodes\r
1051       NULL                        // Insert data\r
1052       );\r
1053 \r
1054     HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1055 \r
1056     //\r
1057     // Refresh the Question value\r
1058     //\r
1059     PrivateData->Configuration.DynamicRefresh++;\r
1060     Status = gRT->SetVariable(\r
1061                     VariableName,\r
1062                     &mFormSetGuid,\r
1063                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1064                     sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
1065                     &PrivateData->Configuration\r
1066                     );\r
1067 \r
1068     //\r
1069     // Change an EFI Variable storage (MyEfiVar) asynchronous, this will cause\r
1070     // the first statement in Form 3 be suppressed\r
1071     //\r
1072     MyVarSize = 1;\r
1073     MyVar = 111;\r
1074     Status = gRT->SetVariable(\r
1075                     L"MyVar",\r
1076                     &mFormSetGuid,\r
1077                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1078                     MyVarSize,\r
1079                     &MyVar\r
1080                     );\r
1081     break;\r
1082 \r
1083   case 0x1237:\r
1084     //\r
1085     // User press "Exit now", request Browser to exit\r
1086     //\r
1087     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
1088     break;\r
1089 \r
1090   case 0x1238:\r
1091     //\r
1092     // User press "Save now", request Browser to save the uncommitted data.\r
1093     //\r
1094     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1095     break;\r
1096 \r
1097   case 0x2000:\r
1098     //\r
1099     // When try to set a new password, user will be chanlleged with old password.\r
1100     // The Callback is responsible for validating old password input by user,\r
1101     // If Callback return EFI_SUCCESS, it indicates validation pass.\r
1102     //\r
1103     switch (PrivateData->PasswordState) {\r
1104     case BROWSER_STATE_VALIDATE_PASSWORD:\r
1105       Status = ValidatePassword (PrivateData, Value->string);\r
1106       if (Status == EFI_SUCCESS) {\r
1107         PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;\r
1108       }\r
1109       break;\r
1110 \r
1111     case BROWSER_STATE_SET_PASSWORD:\r
1112       Status = SetPassword (PrivateData, Value->string);\r
1113       PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
1114       break;\r
1115 \r
1116     default:\r
1117       break;\r
1118     }\r
1119 \r
1120     break;\r
1121 \r
1122   case 0x1111:\r
1123     //\r
1124     // EfiVarstore question takes sample action (print value as debug information) \r
1125     // after read/write question.\r
1126     //\r
1127     MyVarSize = 1;\r
1128     Status = gRT->GetVariable(\r
1129                     L"MyVar",\r
1130                     &mFormSetGuid,\r
1131                     NULL,\r
1132                     &MyVarSize,\r
1133                     &MyVar\r
1134                     );\r
1135     ASSERT_EFI_ERROR (Status);\r
1136     DEBUG ((DEBUG_INFO, "EfiVarstore question: Tall value is %d with value width %d\n", MyVar, MyVarSize));\r
1137   default:\r
1138     break;\r
1139   }\r
1140 \r
1141   return Status;\r
1142 }\r
1143 \r
1144 /**\r
1145   Main entry for this driver.\r
1146 \r
1147   @param ImageHandle     Image handle this driver.\r
1148   @param SystemTable     Pointer to SystemTable.\r
1149 \r
1150   @retval EFI_SUCESS     This function always complete successfully.\r
1151 \r
1152 **/\r
1153 EFI_STATUS\r
1154 EFIAPI\r
1155 DriverSampleInit (\r
1156   IN EFI_HANDLE                   ImageHandle,\r
1157   IN EFI_SYSTEM_TABLE             *SystemTable\r
1158   )\r
1159 {\r
1160   EFI_STATUS                      Status;\r
1161   EFI_HII_HANDLE                  HiiHandle[2];\r
1162   EFI_SCREEN_DESCRIPTOR           Screen;\r
1163   EFI_HII_DATABASE_PROTOCOL       *HiiDatabase;\r
1164   EFI_HII_STRING_PROTOCOL         *HiiString;\r
1165   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;\r
1166   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
1167   CHAR16                          *NewString;\r
1168   UINTN                           BufferSize;\r
1169   DRIVER_SAMPLE_CONFIGURATION     *Configuration;\r
1170   BOOLEAN                         ActionFlag;\r
1171   EFI_STRING                      ConfigRequestHdr;\r
1172 \r
1173   //\r
1174   // Initialize the local variables.\r
1175   //\r
1176   ConfigRequestHdr = NULL;\r
1177   //\r
1178   // Initialize screen dimensions for SendForm().\r
1179   // Remove 3 characters from top and bottom\r
1180   //\r
1181   ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
1182   gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);\r
1183 \r
1184   Screen.TopRow     = 3;\r
1185   Screen.BottomRow  = Screen.BottomRow - 3;\r
1186 \r
1187   //\r
1188   // Initialize driver private data\r
1189   //\r
1190   PrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));\r
1191   if (PrivateData == NULL) {\r
1192     return EFI_OUT_OF_RESOURCES;\r
1193   }\r
1194 \r
1195   PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;\r
1196 \r
1197   PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;\r
1198   PrivateData->ConfigAccess.RouteConfig = RouteConfig;\r
1199   PrivateData->ConfigAccess.Callback = DriverCallback;\r
1200   PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
1201 \r
1202   //\r
1203   // Locate Hii Database protocol\r
1204   //\r
1205   Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);\r
1206   if (EFI_ERROR (Status)) {\r
1207     return Status;\r
1208   }\r
1209   PrivateData->HiiDatabase = HiiDatabase;\r
1210 \r
1211   //\r
1212   // Locate HiiString protocol\r
1213   //\r
1214   Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);\r
1215   if (EFI_ERROR (Status)) {\r
1216     return Status;\r
1217   }\r
1218   PrivateData->HiiString = HiiString;\r
1219 \r
1220   //\r
1221   // Locate Formbrowser2 protocol\r
1222   //\r
1223   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
1224   if (EFI_ERROR (Status)) {\r
1225     return Status;\r
1226   }\r
1227   PrivateData->FormBrowser2 = FormBrowser2;\r
1228 \r
1229   //\r
1230   // Locate ConfigRouting protocol\r
1231   //\r
1232   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
1233   if (EFI_ERROR (Status)) {\r
1234     return Status;\r
1235   }\r
1236   PrivateData->HiiConfigRouting = HiiConfigRouting;\r
1237 \r
1238   Status = gBS->InstallMultipleProtocolInterfaces (\r
1239                   &DriverHandle[0],\r
1240                   &gEfiDevicePathProtocolGuid,\r
1241                   &mHiiVendorDevicePath0,\r
1242                   &gEfiHiiConfigAccessProtocolGuid,\r
1243                   &PrivateData->ConfigAccess,\r
1244                   NULL\r
1245                   );\r
1246   ASSERT_EFI_ERROR (Status);\r
1247 \r
1248   PrivateData->DriverHandle[0] = DriverHandle[0];\r
1249 \r
1250   //\r
1251   // Publish our HII data\r
1252   //\r
1253   HiiHandle[0] = HiiAddPackages (\r
1254                    &mFormSetGuid,\r
1255                    DriverHandle[0],\r
1256                    DriverSampleStrings,\r
1257                    VfrBin,\r
1258                    NULL\r
1259                    );\r
1260   if (HiiHandle[0] == NULL) {\r
1261     return EFI_OUT_OF_RESOURCES;\r
1262   }\r
1263 \r
1264   PrivateData->HiiHandle[0] = HiiHandle[0];\r
1265 \r
1266   //\r
1267   // Publish another Fromset\r
1268   //\r
1269   Status = gBS->InstallMultipleProtocolInterfaces (\r
1270                   &DriverHandle[1],\r
1271                   &gEfiDevicePathProtocolGuid,\r
1272                   &mHiiVendorDevicePath1,\r
1273                   NULL\r
1274                   );\r
1275   ASSERT_EFI_ERROR (Status);\r
1276 \r
1277   PrivateData->DriverHandle[1] = DriverHandle[1];\r
1278 \r
1279   HiiHandle[1] = HiiAddPackages (\r
1280                    &mInventoryGuid,\r
1281                    DriverHandle[1],\r
1282                    DriverSampleStrings,\r
1283                    InventoryBin,\r
1284                    NULL\r
1285                    );\r
1286   if (HiiHandle[1] == NULL) {\r
1287     DriverSampleUnload (ImageHandle);\r
1288     return EFI_OUT_OF_RESOURCES;\r
1289   }\r
1290 \r
1291   PrivateData->HiiHandle[1] = HiiHandle[1];\r
1292 \r
1293   //\r
1294   // Very simple example of how one would update a string that is already\r
1295   // in the HII database\r
1296   //\r
1297   NewString = L"700 Mhz";\r
1298 \r
1299   if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {\r
1300     DriverSampleUnload (ImageHandle);\r
1301     return EFI_OUT_OF_RESOURCES;\r
1302   }\r
1303 \r
1304   HiiSetString (HiiHandle[0], 0, NewString, NULL);\r
1305 \r
1306   //\r
1307   // Initialize Name/Value name String ID\r
1308   //\r
1309   PrivateData->NameStringId[0] = STR_NAME_VALUE_VAR_NAME0;\r
1310   PrivateData->NameStringId[1] = STR_NAME_VALUE_VAR_NAME1;\r
1311   PrivateData->NameStringId[2] = STR_NAME_VALUE_VAR_NAME2;\r
1312 \r
1313   //\r
1314   // Initialize configuration data\r
1315   //\r
1316   Configuration = &PrivateData->Configuration;\r
1317   ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));\r
1318 \r
1319   //\r
1320   // Try to read NV config EFI variable first\r
1321   //\r
1322   ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, DriverHandle[0]);\r
1323   ASSERT (ConfigRequestHdr != NULL);\r
1324 \r
1325   BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
1326   Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);\r
1327   if (EFI_ERROR (Status)) {\r
1328     //\r
1329     // Store zero data Buffer Storage to EFI variable\r
1330     //\r
1331     Status = gRT->SetVariable(\r
1332                     VariableName,\r
1333                     &mFormSetGuid,\r
1334                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1335                     sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
1336                     Configuration\r
1337                     );\r
1338     ASSERT (Status == EFI_SUCCESS);\r
1339     //\r
1340     // EFI variable for NV config doesn't exit, we should build this variable\r
1341     // based on default values stored in IFR\r
1342     //\r
1343     ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);\r
1344     ASSERT (ActionFlag);\r
1345   } else {\r
1346     //\r
1347     // EFI variable does exist and Validate Current Setting\r
1348     //\r
1349     ActionFlag = HiiValidateSettings (ConfigRequestHdr);\r
1350     ASSERT (ActionFlag);\r
1351   }\r
1352 \r
1353   FreePool (ConfigRequestHdr);\r
1354 \r
1355 \r
1356   //\r
1357   // In default, this driver is built into Flash device image,\r
1358   // the following code doesn't run.\r
1359   //\r
1360 \r
1361   //\r
1362   // Example of how to display only the item we sent to HII\r
1363   // When this driver is not built into Flash device image,\r
1364   // it need to call SendForm to show front page by itself.\r
1365   //\r
1366   if (DISPLAY_ONLY_MY_ITEM <= 1) {\r
1367     //\r
1368     // Have the browser pull out our copy of the data, and only display our data\r
1369     //\r
1370     Status = FormBrowser2->SendForm (\r
1371                              FormBrowser2,\r
1372                              &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),\r
1373                              1,\r
1374                              NULL,\r
1375                              0,\r
1376                              NULL,\r
1377                              NULL\r
1378                              );\r
1379 \r
1380     HiiRemovePackages (HiiHandle[0]);\r
1381 \r
1382     HiiRemovePackages (HiiHandle[1]);\r
1383   }\r
1384 \r
1385   return EFI_SUCCESS;\r
1386 }\r
1387 \r
1388 /**\r
1389   Unloads the application and its installed protocol.\r
1390 \r
1391   @param[in]  ImageHandle       Handle that identifies the image to be unloaded.\r
1392 \r
1393   @retval EFI_SUCCESS           The image has been unloaded.\r
1394 **/\r
1395 EFI_STATUS\r
1396 EFIAPI\r
1397 DriverSampleUnload (\r
1398   IN EFI_HANDLE  ImageHandle\r
1399   )\r
1400 {\r
1401   UINTN Index;\r
1402   if (DriverHandle[0] != NULL) {\r
1403     gBS->UninstallMultipleProtocolInterfaces (\r
1404             DriverHandle[0],\r
1405             &gEfiDevicePathProtocolGuid,\r
1406             &mHiiVendorDevicePath0,\r
1407             &gEfiHiiConfigAccessProtocolGuid,\r
1408             &PrivateData->ConfigAccess,\r
1409             NULL\r
1410            );\r
1411     DriverHandle[0] = NULL;\r
1412   }\r
1413 \r
1414   if (DriverHandle[1] != NULL) {\r
1415     gBS->UninstallMultipleProtocolInterfaces (\r
1416             DriverHandle[1],\r
1417             &gEfiDevicePathProtocolGuid,\r
1418             &mHiiVendorDevicePath1,\r
1419             NULL\r
1420            );\r
1421     DriverHandle[1] = NULL;\r
1422   }\r
1423 \r
1424   if (PrivateData->HiiHandle[0] != NULL) {\r
1425     HiiRemovePackages (PrivateData->HiiHandle[0]);\r
1426   }\r
1427 \r
1428   if (PrivateData->HiiHandle[1] != NULL) {\r
1429     HiiRemovePackages (PrivateData->HiiHandle[1]);\r
1430   }\r
1431 \r
1432   if (PrivateData != NULL) {\r
1433     for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {\r
1434       if (PrivateData->NameValueName[Index] != NULL) {\r
1435         FreePool (PrivateData->NameValueName[Index]);\r
1436       }\r
1437     }\r
1438     FreePool (PrivateData);\r
1439     PrivateData = NULL;\r
1440   }\r
1441 \r
1442   return EFI_SUCCESS;\r
1443 }\r