]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
Add Example for EFI_BROWSER_ACTION_RETRIEVE callback
[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 - 2009, 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 || Progress == NULL) {
456 return EFI_INVALID_PARAMETER;
457 }
458
459 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
460 HiiConfigRouting = PrivateData->HiiConfigRouting;
461 *Progress = Configuration;
462
463 //
464 // Check routing data in <ConfigHdr>.
465 // Note: if only one Storage is used, then this checking could be skipped.
466 //
467 if (!HiiIsConfigHdrMatch (Configuration, &mFormSetGuid, VariableName)) {
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 EFI_INPUT_KEY Key;
558 DRIVER_SAMPLE_CONFIGURATION *Configuration;
559 UINTN MyVarSize;
560
561 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
562 //
563 // On FORM_OPEN event, update the form on-the-fly
564 //
565 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
566
567 //
568 // Initialize the container for dynamic opcodes
569 //
570 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
571 ASSERT (StartOpCodeHandle != NULL);
572
573 //
574 // Create Hii Extend Label OpCode as the start opcode
575 //
576 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
577 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
578 StartLabel->Number = LABEL_UPDATE2;
579
580 HiiCreateActionOpCode (
581 StartOpCodeHandle, // Container for dynamic created opcodes
582 0x1238, // Question ID
583 STRING_TOKEN(STR_SAVE_TEXT), // Prompt text
584 STRING_TOKEN(STR_SAVE_TEXT), // Help text
585 EFI_IFR_FLAG_CALLBACK, // Question flag
586 0 // Action String ID
587 );
588
589 HiiUpdateForm (
590 PrivateData->HiiHandle[0], // HII handle
591 &mFormSetGuid, // Formset GUID
592 0x3, // Form ID
593 StartOpCodeHandle, // Label for where to insert opcodes
594 NULL // Insert data
595 );
596
597 HiiFreeOpCodeHandle (StartOpCodeHandle);
598 return EFI_SUCCESS;
599 }
600
601 if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
602 //
603 // On FORM_CLOSE event, show up a pop-up
604 //
605 do {
606 CreatePopUp (
607 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
608 &Key,
609 L"",
610 L"You are going to leave the Form!",
611 L"Press ESC or ENTER to continue ...",
612 L"",
613 NULL
614 );
615 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
616
617 return EFI_SUCCESS;
618 }
619
620 if ((Value == NULL) || (ActionRequest == NULL)) {
621 return EFI_INVALID_PARAMETER;
622 }
623
624 if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0)) {
625 return EFI_INVALID_PARAMETER;
626 }
627
628 Status = EFI_SUCCESS;
629 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
630
631 switch (QuestionId) {
632 case 0x1234:
633 //
634 // Initialize the container for dynamic opcodes
635 //
636 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
637 ASSERT (StartOpCodeHandle != NULL);
638
639 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
640 ASSERT (EndOpCodeHandle != NULL);
641
642 //
643 // Create Hii Extend Label OpCode as the start opcode
644 //
645 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
646 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
647 StartLabel->Number = LABEL_UPDATE1;
648
649 //
650 // Create Hii Extend Label OpCode as the end opcode
651 //
652 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
653 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
654 EndLabel->Number = LABEL_END;
655
656 HiiCreateActionOpCode (
657 StartOpCodeHandle, // Container for dynamic created opcodes
658 0x1237, // Question ID
659 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
660 STRING_TOKEN(STR_EXIT_TEXT), // Help text
661 EFI_IFR_FLAG_CALLBACK, // Question flag
662 0 // Action String ID
663 );
664
665 //
666 // Create Option OpCode
667 //
668 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
669 ASSERT (OptionsOpCodeHandle != NULL);
670
671 HiiCreateOneOfOptionOpCode (
672 OptionsOpCodeHandle,
673 STRING_TOKEN (STR_BOOT_OPTION1),
674 0,
675 EFI_IFR_NUMERIC_SIZE_1,
676 1
677 );
678
679 HiiCreateOneOfOptionOpCode (
680 OptionsOpCodeHandle,
681 STRING_TOKEN (STR_BOOT_OPTION2),
682 0,
683 EFI_IFR_NUMERIC_SIZE_1,
684 2
685 );
686
687 //
688 // Prepare initial value for the dynamic created oneof Question
689 //
690 PrivateData->Configuration.DynamicOneof = 2;
691 Status = gRT->SetVariable(
692 VariableName,
693 &mFormSetGuid,
694 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
695 sizeof (DRIVER_SAMPLE_CONFIGURATION),
696 &PrivateData->Configuration
697 );
698
699 //
700 // Set initial vlaue of dynamic created oneof Question in Form Browser
701 //
702 Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
703 ASSERT (Configuration != NULL);
704 Status = HiiGetBrowserData (&mFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration);
705 if (!EFI_ERROR (Status)) {
706 Configuration->DynamicOneof = 2;
707
708 //
709 // Update uncommitted data of Browser
710 //
711 HiiSetBrowserData (
712 &mFormSetGuid,
713 VariableName,
714 sizeof (DRIVER_SAMPLE_CONFIGURATION),
715 (UINT8 *) Configuration,
716 NULL
717 );
718 }
719 FreePool (Configuration);
720
721 HiiCreateOneOfOpCode (
722 StartOpCodeHandle, // Container for dynamic created opcodes
723 0x8001, // Question ID (or call it "key")
724 CONFIGURATION_VARSTORE_ID, // VarStore ID
725 (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET, // Offset in Buffer Storage
726 STRING_TOKEN (STR_ONE_OF_PROMPT), // Question prompt text
727 STRING_TOKEN (STR_ONE_OF_HELP), // Question help text
728 EFI_IFR_FLAG_CALLBACK, // Question flag
729 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
730 OptionsOpCodeHandle, // Option Opcode list
731 NULL // Default Opcode is NULl
732 );
733
734 HiiCreateOrderedListOpCode (
735 StartOpCodeHandle, // Container for dynamic created opcodes
736 0x8002, // Question ID
737 CONFIGURATION_VARSTORE_ID, // VarStore ID
738 (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
739 STRING_TOKEN (STR_BOOT_OPTIONS), // Question prompt text
740 STRING_TOKEN (STR_BOOT_OPTIONS), // Question help text
741 EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
742 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
743 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
744 5, // Maximum container
745 OptionsOpCodeHandle, // Option Opcode list
746 NULL // Default Opcode is NULl
747 );
748
749 HiiCreateGotoOpCode (
750 StartOpCodeHandle, // Container for dynamic created opcodes
751 1, // Target Form ID
752 STRING_TOKEN (STR_GOTO_FORM1), // Prompt text
753 STRING_TOKEN (STR_GOTO_HELP), // Help text
754 0, // Question flag
755 0x8003 // Question ID
756 );
757
758 HiiUpdateForm (
759 PrivateData->HiiHandle[0], // HII handle
760 &mFormSetGuid, // Formset GUID
761 0x1234, // Form ID
762 StartOpCodeHandle, // Label for where to insert opcodes
763 EndOpCodeHandle // Replace data
764 );
765
766 HiiFreeOpCodeHandle (StartOpCodeHandle);
767 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
768 HiiFreeOpCodeHandle (EndOpCodeHandle);
769 break;
770
771 case 0x5678:
772 //
773 // We will reach here once the Question is refreshed
774 //
775
776 //
777 // Initialize the container for dynamic opcodes
778 //
779 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
780 ASSERT (StartOpCodeHandle != NULL);
781
782 //
783 // Create Hii Extend Label OpCode as the start opcode
784 //
785 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
786 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
787 StartLabel->Number = LABEL_UPDATE2;
788
789 HiiCreateActionOpCode (
790 StartOpCodeHandle, // Container for dynamic created opcodes
791 0x1237, // Question ID
792 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
793 STRING_TOKEN(STR_EXIT_TEXT), // Help text
794 EFI_IFR_FLAG_CALLBACK, // Question flag
795 0 // Action String ID
796 );
797
798 HiiUpdateForm (
799 PrivateData->HiiHandle[0], // HII handle
800 &mFormSetGuid, // Formset GUID
801 0x3, // Form ID
802 StartOpCodeHandle, // Label for where to insert opcodes
803 NULL // Insert data
804 );
805
806 HiiFreeOpCodeHandle (StartOpCodeHandle);
807
808 //
809 // Refresh the Question value
810 //
811 PrivateData->Configuration.DynamicRefresh++;
812 Status = gRT->SetVariable(
813 VariableName,
814 &mFormSetGuid,
815 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
816 sizeof (DRIVER_SAMPLE_CONFIGURATION),
817 &PrivateData->Configuration
818 );
819
820 //
821 // Change an EFI Variable storage (MyEfiVar) asynchronous, this will cause
822 // the first statement in Form 3 be suppressed
823 //
824 MyVarSize = 1;
825 MyVar = 111;
826 Status = gRT->SetVariable(
827 L"MyVar",
828 &mFormSetGuid,
829 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
830 MyVarSize,
831 &MyVar
832 );
833 break;
834
835 case 0x1237:
836 //
837 // User press "Exit now", request Browser to exit
838 //
839 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
840 break;
841
842 case 0x1238:
843 //
844 // User press "Save now", request Browser to save the uncommitted data.
845 //
846 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
847 break;
848
849 case 0x2000:
850 //
851 // When try to set a new password, user will be chanlleged with old password.
852 // The Callback is responsible for validating old password input by user,
853 // If Callback return EFI_SUCCESS, it indicates validation pass.
854 //
855 switch (PrivateData->PasswordState) {
856 case BROWSER_STATE_VALIDATE_PASSWORD:
857 Status = ValidatePassword (PrivateData, Value->string);
858 if (Status == EFI_SUCCESS) {
859 PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
860 }
861 break;
862
863 case BROWSER_STATE_SET_PASSWORD:
864 Status = SetPassword (PrivateData, Value->string);
865 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
866 break;
867
868 default:
869 break;
870 }
871
872 break;
873
874 case 0x1111:
875 //
876 // EfiVarstore question takes sample action (print value as debug information)
877 // after read/write question.
878 //
879 MyVarSize = 1;
880 Status = gRT->GetVariable(
881 L"MyVar",
882 &mFormSetGuid,
883 NULL,
884 &MyVarSize,
885 &MyVar
886 );
887 ASSERT_EFI_ERROR (Status);
888 DEBUG ((DEBUG_INFO, "EfiVarstore question: Tall value is %d with value width %d\n", MyVar, MyVarSize));
889 default:
890 break;
891 }
892
893 return Status;
894 }
895
896 /**
897 Main entry for this driver.
898
899 @param ImageHandle Image handle this driver.
900 @param SystemTable Pointer to SystemTable.
901
902 @retval EFI_SUCESS This function always complete successfully.
903
904 **/
905 EFI_STATUS
906 EFIAPI
907 DriverSampleInit (
908 IN EFI_HANDLE ImageHandle,
909 IN EFI_SYSTEM_TABLE *SystemTable
910 )
911 {
912 EFI_STATUS Status;
913 EFI_HII_HANDLE HiiHandle[2];
914 EFI_SCREEN_DESCRIPTOR Screen;
915 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
916 EFI_HII_STRING_PROTOCOL *HiiString;
917 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
918 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
919 CHAR16 *NewString;
920 UINTN BufferSize;
921 DRIVER_SAMPLE_CONFIGURATION *Configuration;
922 BOOLEAN ActionFlag;
923 EFI_STRING ConfigRequestHdr;
924
925 //
926 // Initialize the local variables.
927 //
928 ConfigRequestHdr = NULL;
929 //
930 // Initialize screen dimensions for SendForm().
931 // Remove 3 characters from top and bottom
932 //
933 ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
934 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
935
936 Screen.TopRow = 3;
937 Screen.BottomRow = Screen.BottomRow - 3;
938
939 //
940 // Initialize driver private data
941 //
942 PrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
943 if (PrivateData == NULL) {
944 return EFI_OUT_OF_RESOURCES;
945 }
946
947 PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
948
949 PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
950 PrivateData->ConfigAccess.RouteConfig = RouteConfig;
951 PrivateData->ConfigAccess.Callback = DriverCallback;
952 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
953
954 //
955 // Locate Hii Database protocol
956 //
957 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
958 if (EFI_ERROR (Status)) {
959 return Status;
960 }
961 PrivateData->HiiDatabase = HiiDatabase;
962
963 //
964 // Locate HiiString protocol
965 //
966 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
967 if (EFI_ERROR (Status)) {
968 return Status;
969 }
970 PrivateData->HiiString = HiiString;
971
972 //
973 // Locate Formbrowser2 protocol
974 //
975 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
976 if (EFI_ERROR (Status)) {
977 return Status;
978 }
979 PrivateData->FormBrowser2 = FormBrowser2;
980
981 //
982 // Locate ConfigRouting protocol
983 //
984 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
985 if (EFI_ERROR (Status)) {
986 return Status;
987 }
988 PrivateData->HiiConfigRouting = HiiConfigRouting;
989
990 Status = gBS->InstallMultipleProtocolInterfaces (
991 &DriverHandle[0],
992 &gEfiDevicePathProtocolGuid,
993 &mHiiVendorDevicePath0,
994 &gEfiHiiConfigAccessProtocolGuid,
995 &PrivateData->ConfigAccess,
996 NULL
997 );
998 ASSERT_EFI_ERROR (Status);
999
1000 PrivateData->DriverHandle[0] = DriverHandle[0];
1001
1002 //
1003 // Publish our HII data
1004 //
1005 HiiHandle[0] = HiiAddPackages (
1006 &mFormSetGuid,
1007 DriverHandle[0],
1008 DriverSampleStrings,
1009 VfrBin,
1010 NULL
1011 );
1012 if (HiiHandle[0] == NULL) {
1013 return EFI_OUT_OF_RESOURCES;
1014 }
1015
1016 PrivateData->HiiHandle[0] = HiiHandle[0];
1017
1018 //
1019 // Publish another Fromset
1020 //
1021 Status = gBS->InstallMultipleProtocolInterfaces (
1022 &DriverHandle[1],
1023 &gEfiDevicePathProtocolGuid,
1024 &mHiiVendorDevicePath1,
1025 NULL
1026 );
1027 ASSERT_EFI_ERROR (Status);
1028
1029 PrivateData->DriverHandle[1] = DriverHandle[1];
1030
1031 HiiHandle[1] = HiiAddPackages (
1032 &mInventoryGuid,
1033 DriverHandle[1],
1034 DriverSampleStrings,
1035 InventoryBin,
1036 NULL
1037 );
1038 if (HiiHandle[1] == NULL) {
1039 return EFI_OUT_OF_RESOURCES;
1040 }
1041
1042 PrivateData->HiiHandle[1] = HiiHandle[1];
1043
1044 //
1045 // Very simple example of how one would update a string that is already
1046 // in the HII database
1047 //
1048 NewString = L"700 Mhz";
1049
1050 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
1051 return EFI_OUT_OF_RESOURCES;
1052 }
1053
1054 //
1055 // Initialize configuration data
1056 //
1057 Configuration = &PrivateData->Configuration;
1058 ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
1059
1060 //
1061 // Try to read NV config EFI variable first
1062 //
1063 ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, DriverHandle[0]);
1064 ASSERT (ConfigRequestHdr != NULL);
1065
1066 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1067 Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);
1068 if (EFI_ERROR (Status)) {
1069 //
1070 // Store zero data Buffer Storage to EFI variable
1071 //
1072 Status = gRT->SetVariable(
1073 VariableName,
1074 &mFormSetGuid,
1075 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1076 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1077 Configuration
1078 );
1079 ASSERT (Status == EFI_SUCCESS);
1080 //
1081 // EFI variable for NV config doesn't exit, we should build this variable
1082 // based on default values stored in IFR
1083 //
1084 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
1085 ASSERT (ActionFlag);
1086 } else {
1087 //
1088 // EFI variable does exist and Validate Current Setting
1089 //
1090 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
1091 ASSERT (ActionFlag);
1092 }
1093
1094 FreePool (ConfigRequestHdr);
1095
1096
1097 //
1098 // In default, this driver is built into Flash device image,
1099 // the following code doesn't run.
1100 //
1101
1102 //
1103 // Example of how to display only the item we sent to HII
1104 // When this driver is not built into Flash device image,
1105 // it need to call SendForm to show front page by itself.
1106 //
1107 if (DISPLAY_ONLY_MY_ITEM <= 1) {
1108 //
1109 // Have the browser pull out our copy of the data, and only display our data
1110 //
1111 Status = FormBrowser2->SendForm (
1112 FormBrowser2,
1113 &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
1114 1,
1115 NULL,
1116 0,
1117 NULL,
1118 NULL
1119 );
1120
1121 HiiRemovePackages (HiiHandle[0]);
1122
1123 HiiRemovePackages (HiiHandle[1]);
1124 }
1125
1126 return EFI_SUCCESS;
1127 }
1128
1129 /**
1130 Unloads the application and its installed protocol.
1131
1132 @param[in] ImageHandle Handle that identifies the image to be unloaded.
1133
1134 @retval EFI_SUCCESS The image has been unloaded.
1135 **/
1136 EFI_STATUS
1137 EFIAPI
1138 DriverSampleUnload (
1139 IN EFI_HANDLE ImageHandle
1140 )
1141 {
1142 if (DriverHandle[0] != NULL) {
1143 gBS->UninstallMultipleProtocolInterfaces (
1144 DriverHandle[0],
1145 &gEfiDevicePathProtocolGuid,
1146 &mHiiVendorDevicePath0,
1147 &gEfiHiiConfigAccessProtocolGuid,
1148 &PrivateData->ConfigAccess,
1149 NULL
1150 );
1151 DriverHandle[0] = NULL;
1152 }
1153
1154 if (DriverHandle[1] != NULL) {
1155 gBS->UninstallMultipleProtocolInterfaces (
1156 DriverHandle[1],
1157 &gEfiDevicePathProtocolGuid,
1158 &mHiiVendorDevicePath1,
1159 NULL
1160 );
1161 DriverHandle[1] = NULL;
1162 }
1163
1164 if (PrivateData->HiiHandle[0] != NULL) {
1165 HiiRemovePackages (PrivateData->HiiHandle[0]);
1166 }
1167
1168 if (PrivateData->HiiHandle[1] != NULL) {
1169 HiiRemovePackages (PrivateData->HiiHandle[1]);
1170 }
1171
1172 if (PrivateData != NULL) {
1173 FreePool (PrivateData);
1174 PrivateData = NULL;
1175 }
1176
1177 return EFI_SUCCESS;
1178 }