]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
Retire original HII APIs: IfrLibExtractDefault and ConstructConfigAltResp, which...
[mirror_edk2.git] / MdeModulePkg / Universal / DriverSampleDxe / DriverSample.c
1 /** @file
2 This is an example of how a driver might export data to the HII protocol to be
3 later utilized by the Setup Protocol
4
5 Copyright (c) 2004 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include "DriverSample.h"
18
19 #define DISPLAY_ONLY_MY_ITEM 0x0002
20
21 EFI_GUID mFormSetGuid = FORMSET_GUID;
22 EFI_GUID mInventoryGuid = INVENTORY_GUID;
23
24 CHAR16 VariableName[] = L"MyIfrNVData";
25
26 EFI_HANDLE DriverHandle[2] = {NULL, NULL};
27 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData = NULL;
28
29 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath0 = {
30 {
31 {
32 HARDWARE_DEVICE_PATH,
33 HW_VENDOR_DP,
34 {
35 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
36 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
37 }
38 },
39 //
40 // {C153B68D-EBFC-488e-B110-662867745B87}
41 //
42 { 0xc153b68d, 0xebfc, 0x488e, { 0xb1, 0x10, 0x66, 0x28, 0x67, 0x74, 0x5b, 0x87 } }
43 },
44 {
45 END_DEVICE_PATH_TYPE,
46 END_ENTIRE_DEVICE_PATH_SUBTYPE,
47 {
48 (UINT8) (END_DEVICE_PATH_LENGTH),
49 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
50 }
51 }
52 };
53
54 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath1 = {
55 {
56 {
57 HARDWARE_DEVICE_PATH,
58 HW_VENDOR_DP,
59 {
60 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
61 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
62 }
63 },
64 //
65 // {06F37F07-0C48-40e9-8436-0A08A0BB76B0}
66 //
67 { 0x6f37f07, 0xc48, 0x40e9, { 0x84, 0x36, 0xa, 0x8, 0xa0, 0xbb, 0x76, 0xb0 } }
68 },
69 {
70 END_DEVICE_PATH_TYPE,
71 END_ENTIRE_DEVICE_PATH_SUBTYPE,
72 {
73 (UINT8) (END_DEVICE_PATH_LENGTH),
74 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
75 }
76 }
77 };
78
79 /**
80 Encode the password using a simple algorithm.
81
82 @param Password The string to be encoded.
83 @param MaxSize The size of the string.
84
85 **/
86 VOID
87 EncodePassword (
88 IN CHAR16 *Password,
89 IN UINTN MaxSize
90 )
91 {
92 UINTN Index;
93 UINTN Loop;
94 CHAR16 *Buffer;
95 CHAR16 *Key;
96
97 Key = L"MAR10648567";
98 Buffer = AllocateZeroPool (MaxSize);
99 ASSERT (Buffer != NULL);
100
101 for (Index = 0; Key[Index] != 0; Index++) {
102 for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {
103 Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);
104 }
105 }
106
107 CopyMem (Password, Buffer, MaxSize);
108
109 FreePool (Buffer);
110 return ;
111 }
112
113 /**
114 Validate the user's password.
115
116 @param PrivateData This driver's private context data.
117 @param StringId The user's input.
118
119 @retval EFI_SUCCESS The user's input matches the password.
120 @retval EFI_NOT_READY The user's input does not match the password.
121 **/
122 EFI_STATUS
123 ValidatePassword (
124 IN DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,
125 IN EFI_STRING_ID StringId
126 )
127 {
128 EFI_STATUS Status;
129 UINTN Index;
130 UINTN BufferSize;
131 UINTN PasswordMaxSize;
132 CHAR16 *Password;
133 CHAR16 *EncodedPassword;
134 BOOLEAN OldPassword;
135
136 //
137 // Get encoded password first
138 //
139 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
140 Status = gRT->GetVariable (
141 VariableName,
142 &mFormSetGuid,
143 NULL,
144 &BufferSize,
145 &PrivateData->Configuration
146 );
147 if (EFI_ERROR (Status)) {
148 //
149 // Old password not exist, prompt for new password
150 //
151 return EFI_SUCCESS;
152 }
153
154 OldPassword = FALSE;
155 PasswordMaxSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);
156 //
157 // Check whether we have any old password set
158 //
159 for (Index = 0; Index < PasswordMaxSize / sizeof (UINT16); Index++) {
160 if (PrivateData->Configuration.WhatIsThePassword2[Index] != 0) {
161 OldPassword = TRUE;
162 break;
163 }
164 }
165 if (!OldPassword) {
166 //
167 // Old password not exist, return EFI_SUCCESS to prompt for new password
168 //
169 return EFI_SUCCESS;
170 }
171
172 //
173 // Get user input password
174 //
175 Password = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);
176 if (Password == NULL) {
177 return EFI_NOT_READY;
178 }
179 if (StrSize (Password) > PasswordMaxSize) {
180 FreePool (Password);
181 return EFI_NOT_READY;
182 }
183
184 //
185 // Validate old password
186 //
187 EncodedPassword = AllocateZeroPool (PasswordMaxSize);
188 ASSERT (EncodedPassword != NULL);
189 StrnCpy (EncodedPassword, Password, StrLen (Password));
190 EncodePassword (EncodedPassword, StrLen (EncodedPassword) * sizeof (CHAR16));
191 if (CompareMem (EncodedPassword, PrivateData->Configuration.WhatIsThePassword2, StrLen (EncodedPassword) * sizeof (CHAR16)) != 0) {
192 //
193 // Old password mismatch, return EFI_NOT_READY to prompt for error message
194 //
195 Status = EFI_NOT_READY;
196 } else {
197 Status = EFI_SUCCESS;
198 }
199
200 FreePool (Password);
201 FreePool (EncodedPassword);
202
203 return Status;
204 }
205
206 /**
207 Encode the password using a simple algorithm.
208
209 @param PrivateData This driver's private context data.
210 @param StringId The password from User.
211
212 @retval EFI_SUCESS The operation is successful.
213 @return Other value if gRT->SetVariable () fails.
214
215 **/
216 EFI_STATUS
217 SetPassword (
218 IN DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,
219 IN EFI_STRING_ID StringId
220 )
221 {
222 EFI_STATUS Status;
223 CHAR16 *Password;
224 CHAR16 *TempPassword;
225 UINTN PasswordSize;
226 DRIVER_SAMPLE_CONFIGURATION *Configuration;
227 UINTN BufferSize;
228
229 //
230 // Get Buffer Storage data from EFI variable
231 //
232 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
233 Status = gRT->GetVariable (
234 VariableName,
235 &mFormSetGuid,
236 NULL,
237 &BufferSize,
238 &PrivateData->Configuration
239 );
240 if (EFI_ERROR (Status)) {
241 return Status;
242 }
243
244 //
245 // Get user input password
246 //
247 Password = &PrivateData->Configuration.WhatIsThePassword2[0];
248 PasswordSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);
249 ZeroMem (Password, PasswordSize);
250
251 TempPassword = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);
252 if (TempPassword == NULL) {
253 return EFI_NOT_READY;
254 }
255 if (StrSize (TempPassword) > PasswordSize) {
256 FreePool (TempPassword);
257 return EFI_NOT_READY;
258 }
259 StrnCpy (Password, TempPassword, StrLen (TempPassword));
260 FreePool (TempPassword);
261
262 //
263 // Retrive uncommitted data from Browser
264 //
265 Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
266 ASSERT (Configuration != NULL);
267 if (HiiGetBrowserData (&mFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
268 //
269 // Update password's clear text in the screen
270 //
271 CopyMem (Configuration->PasswordClearText, Password, StrSize (Password));
272
273 //
274 // Update uncommitted data of Browser
275 //
276 HiiSetBrowserData (
277 &mFormSetGuid,
278 VariableName,
279 sizeof (DRIVER_SAMPLE_CONFIGURATION),
280 (UINT8 *) Configuration,
281 NULL
282 );
283 }
284
285 //
286 // Free Configuration Buffer
287 //
288 FreePool (Configuration);
289
290
291 //
292 // Set password
293 //
294 EncodePassword (Password, StrLen (Password) * 2);
295 Status = gRT->SetVariable(
296 VariableName,
297 &mFormSetGuid,
298 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
299 sizeof (DRIVER_SAMPLE_CONFIGURATION),
300 &PrivateData->Configuration
301 );
302 return Status;
303 }
304
305
306 /**
307 This function allows a caller to extract the current configuration for one
308 or more named elements from the target driver.
309
310 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
311 @param Request A null-terminated Unicode string in
312 <ConfigRequest> format.
313 @param Progress On return, points to a character in the Request
314 string. Points to the string's null terminator if
315 request was successful. Points to the most recent
316 '&' before the first failing name/value pair (or
317 the beginning of the string if the failure is in
318 the first name/value pair) if the request was not
319 successful.
320 @param Results A null-terminated Unicode string in
321 <ConfigAltResp> format which has all values filled
322 in for the names in the Request string. String to
323 be allocated by the called function.
324
325 @retval EFI_SUCCESS The Results is filled with the requested values.
326 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
327 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
328 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
329 driver.
330
331 **/
332 EFI_STATUS
333 EFIAPI
334 ExtractConfig (
335 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
336 IN CONST EFI_STRING Request,
337 OUT EFI_STRING *Progress,
338 OUT EFI_STRING *Results
339 )
340 {
341 EFI_STATUS Status;
342 UINTN BufferSize;
343 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
344 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
345 EFI_STRING ConfigRequestHdr;
346 EFI_STRING ConfigRequest;
347 UINTN Size;
348
349 //
350 // Initialize the local variables.
351 //
352 ConfigRequestHdr = NULL;
353 ConfigRequest = NULL;
354 Size = 0;
355 *Progress = Request;
356
357 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
358 HiiConfigRouting = PrivateData->HiiConfigRouting;
359
360 //
361 // Get Buffer Storage data from EFI variable.
362 // Try to get the current setting from variable.
363 //
364 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
365 gRT->GetVariable (
366 VariableName,
367 &mFormSetGuid,
368 NULL,
369 &BufferSize,
370 &PrivateData->Configuration
371 );
372
373 if (Request == NULL) {
374 //
375 // Request is set to NULL, construct full request string.
376 //
377
378 //
379 // First Set ConfigRequestHdr string.
380 //
381 ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, PrivateData->DriverHandle[0]);
382 ASSERT (ConfigRequestHdr != NULL);
383
384 //
385 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
386 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
387 //
388 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
389 ConfigRequest = AllocateZeroPool (Size);
390 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
391 FreePool (ConfigRequestHdr);
392 } else {
393 ConfigRequest = Request;
394 }
395
396 //
397 // Check routing data in <ConfigHdr>.
398 // Note: if only one Storage is used, then this checking could be skipped.
399 //
400 if (!HiiIsConfigHdrMatch (ConfigRequest, &mFormSetGuid, VariableName)) {
401 if (Request == NULL) {
402 FreePool (ConfigRequest);
403 }
404 return EFI_NOT_FOUND;
405 }
406
407 //
408 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
409 //
410 Status = HiiConfigRouting->BlockToConfig (
411 HiiConfigRouting,
412 ConfigRequest,
413 (UINT8 *) &PrivateData->Configuration,
414 BufferSize,
415 Results,
416 Progress
417 );
418
419 if (Request == NULL) {
420 FreePool (ConfigRequest);
421 *Progress = NULL;
422 }
423
424 return Status;
425 }
426
427
428 /**
429 This function processes the results of changes in configuration.
430
431 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
432 @param Configuration A null-terminated Unicode string in <ConfigResp>
433 format.
434 @param Progress A pointer to a string filled in with the offset of
435 the most recent '&' before the first failing
436 name/value pair (or the beginning of the string if
437 the failure is in the first name/value pair) or
438 the terminating NULL if all was successful.
439
440 @retval EFI_SUCCESS The Results is processed successfully.
441 @retval EFI_INVALID_PARAMETER Configuration is NULL.
442 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
443 driver.
444
445 **/
446 EFI_STATUS
447 EFIAPI
448 RouteConfig (
449 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
450 IN CONST EFI_STRING Configuration,
451 OUT EFI_STRING *Progress
452 )
453 {
454 EFI_STATUS Status;
455 UINTN BufferSize;
456 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
457 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
458
459 if (Configuration == NULL) {
460 return EFI_INVALID_PARAMETER;
461 }
462
463 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
464 HiiConfigRouting = PrivateData->HiiConfigRouting;
465
466 //
467 // Check routing data in <ConfigHdr>.
468 // Note: if only one Storage is used, then this checking could be skipped.
469 //
470 if (!HiiIsConfigHdrMatch (Configuration, &mFormSetGuid, VariableName)) {
471 *Progress = Configuration;
472 return EFI_NOT_FOUND;
473 }
474
475 //
476 // Get Buffer Storage data from EFI variable
477 //
478 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
479 gRT->GetVariable (
480 VariableName,
481 &mFormSetGuid,
482 NULL,
483 &BufferSize,
484 &PrivateData->Configuration
485 );
486
487 //
488 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
489 //
490 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
491 Status = HiiConfigRouting->ConfigToBlock (
492 HiiConfigRouting,
493 Configuration,
494 (UINT8 *) &PrivateData->Configuration,
495 &BufferSize,
496 Progress
497 );
498 if (EFI_ERROR (Status)) {
499 return Status;
500 }
501
502 //
503 // Store Buffer Storage back to EFI variable
504 //
505 Status = gRT->SetVariable(
506 VariableName,
507 &mFormSetGuid,
508 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
509 sizeof (DRIVER_SAMPLE_CONFIGURATION),
510 &PrivateData->Configuration
511 );
512
513 return Status;
514 }
515
516
517 /**
518 This function processes the results of changes in configuration.
519
520 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
521 @param Action Specifies the type of action taken by the browser.
522 @param QuestionId A unique value which is sent to the original
523 exporting driver so that it can identify the type
524 of data to expect.
525 @param Type The type of value for the question.
526 @param Value A pointer to the data being sent to the original
527 exporting driver.
528 @param ActionRequest On return, points to the action requested by the
529 callback function.
530
531 @retval EFI_SUCCESS The callback successfully handled the action.
532 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
533 variable and its data.
534 @retval EFI_DEVICE_ERROR The variable could not be saved.
535 @retval EFI_UNSUPPORTED The specified Action is not supported by the
536 callback.
537
538 **/
539 EFI_STATUS
540 EFIAPI
541 DriverCallback (
542 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
543 IN EFI_BROWSER_ACTION Action,
544 IN EFI_QUESTION_ID QuestionId,
545 IN UINT8 Type,
546 IN EFI_IFR_TYPE_VALUE *Value,
547 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
548 )
549 {
550 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
551 EFI_STATUS Status;
552 UINT8 MyVar;
553 VOID *StartOpCodeHandle;
554 VOID *OptionsOpCodeHandle;
555 EFI_IFR_GUID_LABEL *StartLabel;
556 VOID *EndOpCodeHandle;
557 EFI_IFR_GUID_LABEL *EndLabel;
558
559 if ((Value == NULL) || (ActionRequest == NULL)) {
560 return EFI_INVALID_PARAMETER;
561 }
562
563 if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0)) {
564 return EFI_INVALID_PARAMETER;
565 }
566
567
568 Status = EFI_SUCCESS;
569 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
570
571 switch (QuestionId) {
572 case 0x1234:
573 //
574 // Initialize the container for dynamic opcodes
575 //
576 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
577 ASSERT (StartOpCodeHandle != NULL);
578
579 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
580 ASSERT (EndOpCodeHandle != NULL);
581
582 //
583 // Create Hii Extend Label OpCode as the start opcode
584 //
585 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
586 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
587 StartLabel->Number = LABEL_UPDATE1;
588
589 //
590 // Create Hii Extend Label OpCode as the end opcode
591 //
592 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
593 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
594 EndLabel->Number = LABEL_END;
595
596 HiiCreateActionOpCode (
597 StartOpCodeHandle, // Container for dynamic created opcodes
598 0x1237, // Question ID
599 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
600 STRING_TOKEN(STR_EXIT_TEXT), // Help text
601 EFI_IFR_FLAG_CALLBACK, // Question flag
602 0 // Action String ID
603 );
604
605 //
606 // Create Option OpCode
607 //
608 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
609 ASSERT (OptionsOpCodeHandle != NULL);
610
611 HiiCreateOneOfOptionOpCode (
612 OptionsOpCodeHandle,
613 STRING_TOKEN (STR_BOOT_OPTION1),
614 0,
615 EFI_IFR_NUMERIC_SIZE_1,
616 1
617 );
618
619 HiiCreateOneOfOptionOpCode (
620 OptionsOpCodeHandle,
621 STRING_TOKEN (STR_BOOT_OPTION2),
622 0,
623 EFI_IFR_NUMERIC_SIZE_1,
624 2
625 );
626
627 //
628 // Prepare initial value for the dynamic created oneof Question
629 //
630 PrivateData->Configuration.DynamicOneof = 2;
631 Status = gRT->SetVariable(
632 VariableName,
633 &mFormSetGuid,
634 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
635 sizeof (DRIVER_SAMPLE_CONFIGURATION),
636 &PrivateData->Configuration
637 );
638
639 HiiCreateOneOfOpCode (
640 StartOpCodeHandle, // Container for dynamic created opcodes
641 0x8001, // Question ID (or call it "key")
642 CONFIGURATION_VARSTORE_ID, // VarStore ID
643 (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET, // Offset in Buffer Storage
644 STRING_TOKEN (STR_ONE_OF_PROMPT), // Question prompt text
645 STRING_TOKEN (STR_ONE_OF_HELP), // Question help text
646 EFI_IFR_FLAG_CALLBACK, // Question flag
647 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
648 OptionsOpCodeHandle, // Option Opcode list
649 NULL // Default Opcode is NULl
650 );
651
652 HiiCreateOrderedListOpCode (
653 StartOpCodeHandle, // Container for dynamic created opcodes
654 0x8002, // Question ID
655 CONFIGURATION_VARSTORE_ID, // VarStore ID
656 (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
657 STRING_TOKEN (STR_BOOT_OPTIONS), // Question prompt text
658 STRING_TOKEN (STR_BOOT_OPTIONS), // Question help text
659 EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
660 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
661 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
662 5, // Maximum container
663 OptionsOpCodeHandle, // Option Opcode list
664 NULL // Default Opcode is NULl
665 );
666
667 HiiCreateGotoOpCode (
668 StartOpCodeHandle, // Container for dynamic created opcodes
669 1, // Target Form ID
670 STRING_TOKEN (STR_GOTO_FORM1), // Prompt text
671 STRING_TOKEN (STR_GOTO_HELP), // Help text
672 0, // Question flag
673 0x8003 // Question ID
674 );
675
676 HiiUpdateForm (
677 PrivateData->HiiHandle[0], // HII handle
678 &mFormSetGuid, // Formset GUID
679 0x1234, // Form ID
680 StartOpCodeHandle, // Label for where to insert opcodes
681 EndOpCodeHandle // Replace data
682 );
683
684 HiiFreeOpCodeHandle (StartOpCodeHandle);
685 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
686 break;
687
688 case 0x5678:
689 //
690 // We will reach here once the Question is refreshed
691 //
692
693 //
694 // Initialize the container for dynamic opcodes
695 //
696 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
697 ASSERT (StartOpCodeHandle != NULL);
698
699 //
700 // Create Hii Extend Label OpCode as the start opcode
701 //
702 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
703 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
704 StartLabel->Number = LABEL_UPDATE2;
705
706 HiiCreateActionOpCode (
707 StartOpCodeHandle, // Container for dynamic created opcodes
708 0x1237, // Question ID
709 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
710 STRING_TOKEN(STR_EXIT_TEXT), // Help text
711 EFI_IFR_FLAG_CALLBACK, // Question flag
712 0 // Action String ID
713 );
714
715 HiiUpdateForm (
716 PrivateData->HiiHandle[0], // HII handle
717 &mFormSetGuid, // Formset GUID
718 0x3, // Form ID
719 StartOpCodeHandle, // Label for where to insert opcodes
720 NULL // Insert data
721 );
722
723 HiiFreeOpCodeHandle (StartOpCodeHandle);
724
725 //
726 // Refresh the Question value
727 //
728 PrivateData->Configuration.DynamicRefresh++;
729 Status = gRT->SetVariable(
730 VariableName,
731 &mFormSetGuid,
732 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
733 sizeof (DRIVER_SAMPLE_CONFIGURATION),
734 &PrivateData->Configuration
735 );
736
737 //
738 // Change an EFI Variable storage (MyEfiVar) asynchronous, this will cause
739 // the first statement in Form 3 be suppressed
740 //
741 MyVar = 111;
742 Status = gRT->SetVariable(
743 L"MyVar",
744 &mFormSetGuid,
745 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
746 1,
747 &MyVar
748 );
749 break;
750
751 case 0x1237:
752 //
753 // User press "Exit now", request Browser to exit
754 //
755 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
756 break;
757
758 case 0x1238:
759 //
760 // User press "Save now", request Browser to save the uncommitted data.
761 //
762 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
763 break;
764
765 case 0x2000:
766 //
767 // When try to set a new password, user will be chanlleged with old password.
768 // The Callback is responsible for validating old password input by user,
769 // If Callback return EFI_SUCCESS, it indicates validation pass.
770 //
771 switch (PrivateData->PasswordState) {
772 case BROWSER_STATE_VALIDATE_PASSWORD:
773 Status = ValidatePassword (PrivateData, Value->string);
774 if (Status == EFI_SUCCESS) {
775 PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
776 }
777 break;
778
779 case BROWSER_STATE_SET_PASSWORD:
780 Status = SetPassword (PrivateData, Value->string);
781 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
782 break;
783
784 default:
785 break;
786 }
787
788 break;
789
790 default:
791 break;
792 }
793
794 return Status;
795 }
796
797 /**
798 Main entry for this driver.
799
800 @param ImageHandle Image handle this driver.
801 @param SystemTable Pointer to SystemTable.
802
803 @retval EFI_SUCESS This function always complete successfully.
804
805 **/
806 EFI_STATUS
807 EFIAPI
808 DriverSampleInit (
809 IN EFI_HANDLE ImageHandle,
810 IN EFI_SYSTEM_TABLE *SystemTable
811 )
812 {
813 EFI_STATUS Status;
814 EFI_HII_HANDLE HiiHandle[2];
815 EFI_SCREEN_DESCRIPTOR Screen;
816 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
817 EFI_HII_STRING_PROTOCOL *HiiString;
818 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
819 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
820 CHAR16 *NewString;
821 UINTN BufferSize;
822 DRIVER_SAMPLE_CONFIGURATION *Configuration;
823 BOOLEAN ActionFlag;
824 EFI_STRING ConfigRequestHdr;
825
826 //
827 // Initialize the local variables.
828 //
829 ConfigRequestHdr = NULL;
830
831 //
832 // Initialize screen dimensions for SendForm().
833 // Remove 3 characters from top and bottom
834 //
835 ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
836 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
837
838 Screen.TopRow = 3;
839 Screen.BottomRow = Screen.BottomRow - 3;
840
841 //
842 // Initialize driver private data
843 //
844 PrivateData = AllocatePool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
845 if (PrivateData == NULL) {
846 return EFI_OUT_OF_RESOURCES;
847 }
848
849 PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
850
851 PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
852 PrivateData->ConfigAccess.RouteConfig = RouteConfig;
853 PrivateData->ConfigAccess.Callback = DriverCallback;
854 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
855
856 //
857 // Locate Hii Database protocol
858 //
859 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
860 if (EFI_ERROR (Status)) {
861 return Status;
862 }
863 PrivateData->HiiDatabase = HiiDatabase;
864
865 //
866 // Locate HiiString protocol
867 //
868 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
869 if (EFI_ERROR (Status)) {
870 return Status;
871 }
872 PrivateData->HiiString = HiiString;
873
874 //
875 // Locate Formbrowser2 protocol
876 //
877 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
878 if (EFI_ERROR (Status)) {
879 return Status;
880 }
881 PrivateData->FormBrowser2 = FormBrowser2;
882
883 //
884 // Locate ConfigRouting protocol
885 //
886 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
887 if (EFI_ERROR (Status)) {
888 return Status;
889 }
890 PrivateData->HiiConfigRouting = HiiConfigRouting;
891
892 Status = gBS->InstallMultipleProtocolInterfaces (
893 &DriverHandle[0],
894 &gEfiDevicePathProtocolGuid,
895 &mHiiVendorDevicePath0,
896 &gEfiHiiConfigAccessProtocolGuid,
897 &PrivateData->ConfigAccess,
898 NULL
899 );
900 ASSERT_EFI_ERROR (Status);
901
902 PrivateData->DriverHandle[0] = DriverHandle[0];
903
904 //
905 // Publish our HII data
906 //
907 HiiHandle[0] = HiiAddPackages (
908 &mFormSetGuid,
909 DriverHandle[0],
910 DriverSampleStrings,
911 VfrBin,
912 NULL
913 );
914 if (HiiHandle[0] == NULL) {
915 return EFI_OUT_OF_RESOURCES;
916 }
917
918 PrivateData->HiiHandle[0] = HiiHandle[0];
919
920 //
921 // Publish another Fromset
922 //
923 Status = gBS->InstallMultipleProtocolInterfaces (
924 &DriverHandle[1],
925 &gEfiDevicePathProtocolGuid,
926 &mHiiVendorDevicePath1,
927 NULL
928 );
929 ASSERT_EFI_ERROR (Status);
930
931 PrivateData->DriverHandle[1] = DriverHandle[1];
932
933 HiiHandle[1] = HiiAddPackages (
934 &mInventoryGuid,
935 DriverHandle[1],
936 DriverSampleStrings,
937 InventoryBin,
938 NULL
939 );
940 if (HiiHandle[1] == NULL) {
941 return EFI_OUT_OF_RESOURCES;
942 }
943
944 PrivateData->HiiHandle[1] = HiiHandle[1];
945
946 //
947 // Very simple example of how one would update a string that is already
948 // in the HII database
949 //
950 NewString = L"700 Mhz";
951
952 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
953 return EFI_OUT_OF_RESOURCES;
954 }
955
956 //
957 // Initialize configuration data
958 //
959 Configuration = &PrivateData->Configuration;
960 ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
961
962 //
963 // Try to read NV config EFI variable first
964 //
965 ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, DriverHandle[0]);
966 ASSERT (ConfigRequestHdr != NULL);
967
968 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
969 Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);
970 if (EFI_ERROR (Status)) {
971 //
972 // EFI variable for NV config doesn't exit, we should build this variable
973 // based on default values stored in IFR
974 //
975 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
976 ASSERT (ActionFlag);
977 } else {
978 //
979 // EFI variable does exist and Validate Current Setting
980 //
981 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
982 ASSERT (ActionFlag);
983 }
984
985 FreePool (ConfigRequestHdr);
986
987
988 //
989 // In default, this driver is built into Flash device image,
990 // the following code doesn't run.
991 //
992
993 //
994 // Example of how to display only the item we sent to HII
995 // When this driver is not built into Flash device image,
996 // it need to call SendForm to show front page by itself.
997 //
998 if (DISPLAY_ONLY_MY_ITEM <= 1) {
999 //
1000 // Have the browser pull out our copy of the data, and only display our data
1001 //
1002 Status = FormBrowser2->SendForm (
1003 FormBrowser2,
1004 &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
1005 1,
1006 NULL,
1007 0,
1008 NULL,
1009 NULL
1010 );
1011
1012 HiiRemovePackages (HiiHandle[0]);
1013
1014 HiiRemovePackages (HiiHandle[1]);
1015 }
1016
1017 return EFI_SUCCESS;
1018 }
1019
1020 /**
1021 Unloads the application and its installed protocol.
1022
1023 @param[in] ImageHandle Handle that identifies the image to be unloaded.
1024
1025 @retval EFI_SUCCESS The image has been unloaded.
1026 **/
1027 EFI_STATUS
1028 EFIAPI
1029 DriverSampleUnload (
1030 IN EFI_HANDLE ImageHandle
1031 )
1032 {
1033 if (DriverHandle[0] != NULL) {
1034 gBS->UninstallMultipleProtocolInterfaces (
1035 DriverHandle[0],
1036 &gEfiDevicePathProtocolGuid,
1037 &mHiiVendorDevicePath0,
1038 &gEfiHiiConfigAccessProtocolGuid,
1039 &PrivateData->ConfigAccess,
1040 NULL
1041 );
1042 }
1043
1044 if (DriverHandle[1] != NULL) {
1045 gBS->UninstallMultipleProtocolInterfaces (
1046 DriverHandle[1],
1047 &gEfiDevicePathProtocolGuid,
1048 &mHiiVendorDevicePath1,
1049 NULL
1050 );
1051 }
1052
1053 if (PrivateData->HiiHandle[0] != NULL) {
1054 HiiRemovePackages (PrivateData->HiiHandle[0]);
1055 }
1056
1057 if (PrivateData->HiiHandle[1] != NULL) {
1058 HiiRemovePackages (PrivateData->HiiHandle[1]);
1059 }
1060
1061 if (PrivateData != NULL) {
1062 FreePool (PrivateData);
1063 }
1064
1065 return EFI_SUCCESS;
1066 }