]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
Add example usage of EFI_BROWSER_ACTION_FORM_OPEN and EFI_BROWSER_ACTION_FORM_CLOSE...
[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
560 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
561 //
562 // On FORM_OPEN event, update the form on-the-fly
563 //
564 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
565
566 //
567 // Initialize the container for dynamic opcodes
568 //
569 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
570 ASSERT (StartOpCodeHandle != NULL);
571
572 //
573 // Create Hii Extend Label OpCode as the start opcode
574 //
575 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
576 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
577 StartLabel->Number = LABEL_UPDATE2;
578
579 HiiCreateActionOpCode (
580 StartOpCodeHandle, // Container for dynamic created opcodes
581 0x1238, // Question ID
582 STRING_TOKEN(STR_SAVE_TEXT), // Prompt text
583 STRING_TOKEN(STR_SAVE_TEXT), // Help text
584 EFI_IFR_FLAG_CALLBACK, // Question flag
585 0 // Action String ID
586 );
587
588 HiiUpdateForm (
589 PrivateData->HiiHandle[0], // HII handle
590 &mFormSetGuid, // Formset GUID
591 0x3, // Form ID
592 StartOpCodeHandle, // Label for where to insert opcodes
593 NULL // Insert data
594 );
595
596 HiiFreeOpCodeHandle (StartOpCodeHandle);
597 return EFI_SUCCESS;
598 }
599
600 if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
601 //
602 // On FORM_CLOSE event, show up a pop-up
603 //
604 do {
605 CreatePopUp (
606 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
607 &Key,
608 L"",
609 L"You are going to leave the Form!",
610 L"Press ESC or ENTER to continue ...",
611 L"",
612 NULL
613 );
614 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
615
616 return EFI_SUCCESS;
617 }
618
619 if ((Value == NULL) || (ActionRequest == NULL)) {
620 return EFI_INVALID_PARAMETER;
621 }
622
623 if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0)) {
624 return EFI_INVALID_PARAMETER;
625 }
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 MyVar = 111;
825 Status = gRT->SetVariable(
826 L"MyVar",
827 &mFormSetGuid,
828 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
829 1,
830 &MyVar
831 );
832 break;
833
834 case 0x1237:
835 //
836 // User press "Exit now", request Browser to exit
837 //
838 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
839 break;
840
841 case 0x1238:
842 //
843 // User press "Save now", request Browser to save the uncommitted data.
844 //
845 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
846 break;
847
848 case 0x2000:
849 //
850 // When try to set a new password, user will be chanlleged with old password.
851 // The Callback is responsible for validating old password input by user,
852 // If Callback return EFI_SUCCESS, it indicates validation pass.
853 //
854 switch (PrivateData->PasswordState) {
855 case BROWSER_STATE_VALIDATE_PASSWORD:
856 Status = ValidatePassword (PrivateData, Value->string);
857 if (Status == EFI_SUCCESS) {
858 PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
859 }
860 break;
861
862 case BROWSER_STATE_SET_PASSWORD:
863 Status = SetPassword (PrivateData, Value->string);
864 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
865 break;
866
867 default:
868 break;
869 }
870
871 break;
872
873 default:
874 break;
875 }
876
877 return Status;
878 }
879
880 /**
881 Main entry for this driver.
882
883 @param ImageHandle Image handle this driver.
884 @param SystemTable Pointer to SystemTable.
885
886 @retval EFI_SUCESS This function always complete successfully.
887
888 **/
889 EFI_STATUS
890 EFIAPI
891 DriverSampleInit (
892 IN EFI_HANDLE ImageHandle,
893 IN EFI_SYSTEM_TABLE *SystemTable
894 )
895 {
896 EFI_STATUS Status;
897 EFI_HII_HANDLE HiiHandle[2];
898 EFI_SCREEN_DESCRIPTOR Screen;
899 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
900 EFI_HII_STRING_PROTOCOL *HiiString;
901 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
902 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
903 CHAR16 *NewString;
904 UINTN BufferSize;
905 DRIVER_SAMPLE_CONFIGURATION *Configuration;
906 BOOLEAN ActionFlag;
907 EFI_STRING ConfigRequestHdr;
908
909 //
910 // Initialize the local variables.
911 //
912 ConfigRequestHdr = NULL;
913 //
914 // Initialize screen dimensions for SendForm().
915 // Remove 3 characters from top and bottom
916 //
917 ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
918 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
919
920 Screen.TopRow = 3;
921 Screen.BottomRow = Screen.BottomRow - 3;
922
923 //
924 // Initialize driver private data
925 //
926 PrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
927 if (PrivateData == NULL) {
928 return EFI_OUT_OF_RESOURCES;
929 }
930
931 PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
932
933 PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
934 PrivateData->ConfigAccess.RouteConfig = RouteConfig;
935 PrivateData->ConfigAccess.Callback = DriverCallback;
936 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
937
938 //
939 // Locate Hii Database protocol
940 //
941 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
942 if (EFI_ERROR (Status)) {
943 return Status;
944 }
945 PrivateData->HiiDatabase = HiiDatabase;
946
947 //
948 // Locate HiiString protocol
949 //
950 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
951 if (EFI_ERROR (Status)) {
952 return Status;
953 }
954 PrivateData->HiiString = HiiString;
955
956 //
957 // Locate Formbrowser2 protocol
958 //
959 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
960 if (EFI_ERROR (Status)) {
961 return Status;
962 }
963 PrivateData->FormBrowser2 = FormBrowser2;
964
965 //
966 // Locate ConfigRouting protocol
967 //
968 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
969 if (EFI_ERROR (Status)) {
970 return Status;
971 }
972 PrivateData->HiiConfigRouting = HiiConfigRouting;
973
974 Status = gBS->InstallMultipleProtocolInterfaces (
975 &DriverHandle[0],
976 &gEfiDevicePathProtocolGuid,
977 &mHiiVendorDevicePath0,
978 &gEfiHiiConfigAccessProtocolGuid,
979 &PrivateData->ConfigAccess,
980 NULL
981 );
982 ASSERT_EFI_ERROR (Status);
983
984 PrivateData->DriverHandle[0] = DriverHandle[0];
985
986 //
987 // Publish our HII data
988 //
989 HiiHandle[0] = HiiAddPackages (
990 &mFormSetGuid,
991 DriverHandle[0],
992 DriverSampleStrings,
993 VfrBin,
994 NULL
995 );
996 if (HiiHandle[0] == NULL) {
997 return EFI_OUT_OF_RESOURCES;
998 }
999
1000 PrivateData->HiiHandle[0] = HiiHandle[0];
1001
1002 //
1003 // Publish another Fromset
1004 //
1005 Status = gBS->InstallMultipleProtocolInterfaces (
1006 &DriverHandle[1],
1007 &gEfiDevicePathProtocolGuid,
1008 &mHiiVendorDevicePath1,
1009 NULL
1010 );
1011 ASSERT_EFI_ERROR (Status);
1012
1013 PrivateData->DriverHandle[1] = DriverHandle[1];
1014
1015 HiiHandle[1] = HiiAddPackages (
1016 &mInventoryGuid,
1017 DriverHandle[1],
1018 DriverSampleStrings,
1019 InventoryBin,
1020 NULL
1021 );
1022 if (HiiHandle[1] == NULL) {
1023 return EFI_OUT_OF_RESOURCES;
1024 }
1025
1026 PrivateData->HiiHandle[1] = HiiHandle[1];
1027
1028 //
1029 // Very simple example of how one would update a string that is already
1030 // in the HII database
1031 //
1032 NewString = L"700 Mhz";
1033
1034 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
1035 return EFI_OUT_OF_RESOURCES;
1036 }
1037
1038 //
1039 // Initialize configuration data
1040 //
1041 Configuration = &PrivateData->Configuration;
1042 ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
1043
1044 //
1045 // Try to read NV config EFI variable first
1046 //
1047 ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, DriverHandle[0]);
1048 ASSERT (ConfigRequestHdr != NULL);
1049
1050 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1051 Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);
1052 if (EFI_ERROR (Status)) {
1053 //
1054 // Store zero data Buffer Storage to EFI variable
1055 //
1056 Status = gRT->SetVariable(
1057 VariableName,
1058 &mFormSetGuid,
1059 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1060 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1061 Configuration
1062 );
1063 ASSERT (Status == EFI_SUCCESS);
1064 //
1065 // EFI variable for NV config doesn't exit, we should build this variable
1066 // based on default values stored in IFR
1067 //
1068 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
1069 ASSERT (ActionFlag);
1070 } else {
1071 //
1072 // EFI variable does exist and Validate Current Setting
1073 //
1074 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
1075 ASSERT (ActionFlag);
1076 }
1077
1078 FreePool (ConfigRequestHdr);
1079
1080
1081 //
1082 // In default, this driver is built into Flash device image,
1083 // the following code doesn't run.
1084 //
1085
1086 //
1087 // Example of how to display only the item we sent to HII
1088 // When this driver is not built into Flash device image,
1089 // it need to call SendForm to show front page by itself.
1090 //
1091 if (DISPLAY_ONLY_MY_ITEM <= 1) {
1092 //
1093 // Have the browser pull out our copy of the data, and only display our data
1094 //
1095 Status = FormBrowser2->SendForm (
1096 FormBrowser2,
1097 &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
1098 1,
1099 NULL,
1100 0,
1101 NULL,
1102 NULL
1103 );
1104
1105 HiiRemovePackages (HiiHandle[0]);
1106
1107 HiiRemovePackages (HiiHandle[1]);
1108 }
1109
1110 return EFI_SUCCESS;
1111 }
1112
1113 /**
1114 Unloads the application and its installed protocol.
1115
1116 @param[in] ImageHandle Handle that identifies the image to be unloaded.
1117
1118 @retval EFI_SUCCESS The image has been unloaded.
1119 **/
1120 EFI_STATUS
1121 EFIAPI
1122 DriverSampleUnload (
1123 IN EFI_HANDLE ImageHandle
1124 )
1125 {
1126 if (DriverHandle[0] != NULL) {
1127 gBS->UninstallMultipleProtocolInterfaces (
1128 DriverHandle[0],
1129 &gEfiDevicePathProtocolGuid,
1130 &mHiiVendorDevicePath0,
1131 &gEfiHiiConfigAccessProtocolGuid,
1132 &PrivateData->ConfigAccess,
1133 NULL
1134 );
1135 DriverHandle[0] = NULL;
1136 }
1137
1138 if (DriverHandle[1] != NULL) {
1139 gBS->UninstallMultipleProtocolInterfaces (
1140 DriverHandle[1],
1141 &gEfiDevicePathProtocolGuid,
1142 &mHiiVendorDevicePath1,
1143 NULL
1144 );
1145 DriverHandle[1] = NULL;
1146 }
1147
1148 if (PrivateData->HiiHandle[0] != NULL) {
1149 HiiRemovePackages (PrivateData->HiiHandle[0]);
1150 }
1151
1152 if (PrivateData->HiiHandle[1] != NULL) {
1153 HiiRemovePackages (PrivateData->HiiHandle[1]);
1154 }
1155
1156 if (PrivateData != NULL) {
1157 FreePool (PrivateData);
1158 PrivateData = NULL;
1159 }
1160
1161 return EFI_SUCCESS;
1162 }