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