]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
Fix incorrect return status usage of HiiGetBrowserData().
[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 if (HiiGetBrowserData (&mFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
705 Configuration->DynamicOneof = 2;
706
707 //
708 // Update uncommitted data of Browser
709 //
710 HiiSetBrowserData (
711 &mFormSetGuid,
712 VariableName,
713 sizeof (DRIVER_SAMPLE_CONFIGURATION),
714 (UINT8 *) Configuration,
715 NULL
716 );
717 }
718 FreePool (Configuration);
719
720 HiiCreateOneOfOpCode (
721 StartOpCodeHandle, // Container for dynamic created opcodes
722 0x8001, // Question ID (or call it "key")
723 CONFIGURATION_VARSTORE_ID, // VarStore ID
724 (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET, // Offset in Buffer Storage
725 STRING_TOKEN (STR_ONE_OF_PROMPT), // Question prompt text
726 STRING_TOKEN (STR_ONE_OF_HELP), // Question help text
727 EFI_IFR_FLAG_CALLBACK, // Question flag
728 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
729 OptionsOpCodeHandle, // Option Opcode list
730 NULL // Default Opcode is NULl
731 );
732
733 HiiCreateOrderedListOpCode (
734 StartOpCodeHandle, // Container for dynamic created opcodes
735 0x8002, // Question ID
736 CONFIGURATION_VARSTORE_ID, // VarStore ID
737 (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
738 STRING_TOKEN (STR_BOOT_OPTIONS), // Question prompt text
739 STRING_TOKEN (STR_BOOT_OPTIONS), // Question help text
740 EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
741 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
742 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
743 5, // Maximum container
744 OptionsOpCodeHandle, // Option Opcode list
745 NULL // Default Opcode is NULl
746 );
747
748 HiiCreateGotoOpCode (
749 StartOpCodeHandle, // Container for dynamic created opcodes
750 1, // Target Form ID
751 STRING_TOKEN (STR_GOTO_FORM1), // Prompt text
752 STRING_TOKEN (STR_GOTO_HELP), // Help text
753 0, // Question flag
754 0x8003 // Question ID
755 );
756
757 HiiUpdateForm (
758 PrivateData->HiiHandle[0], // HII handle
759 &mFormSetGuid, // Formset GUID
760 0x1234, // Form ID
761 StartOpCodeHandle, // Label for where to insert opcodes
762 EndOpCodeHandle // Replace data
763 );
764
765 HiiFreeOpCodeHandle (StartOpCodeHandle);
766 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
767 HiiFreeOpCodeHandle (EndOpCodeHandle);
768 break;
769
770 case 0x5678:
771 //
772 // We will reach here once the Question is refreshed
773 //
774
775 //
776 // Initialize the container for dynamic opcodes
777 //
778 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
779 ASSERT (StartOpCodeHandle != NULL);
780
781 //
782 // Create Hii Extend Label OpCode as the start opcode
783 //
784 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
785 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
786 StartLabel->Number = LABEL_UPDATE2;
787
788 HiiCreateActionOpCode (
789 StartOpCodeHandle, // Container for dynamic created opcodes
790 0x1237, // Question ID
791 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
792 STRING_TOKEN(STR_EXIT_TEXT), // Help text
793 EFI_IFR_FLAG_CALLBACK, // Question flag
794 0 // Action String ID
795 );
796
797 HiiUpdateForm (
798 PrivateData->HiiHandle[0], // HII handle
799 &mFormSetGuid, // Formset GUID
800 0x3, // Form ID
801 StartOpCodeHandle, // Label for where to insert opcodes
802 NULL // Insert data
803 );
804
805 HiiFreeOpCodeHandle (StartOpCodeHandle);
806
807 //
808 // Refresh the Question value
809 //
810 PrivateData->Configuration.DynamicRefresh++;
811 Status = gRT->SetVariable(
812 VariableName,
813 &mFormSetGuid,
814 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
815 sizeof (DRIVER_SAMPLE_CONFIGURATION),
816 &PrivateData->Configuration
817 );
818
819 //
820 // Change an EFI Variable storage (MyEfiVar) asynchronous, this will cause
821 // the first statement in Form 3 be suppressed
822 //
823 MyVarSize = 1;
824 MyVar = 111;
825 Status = gRT->SetVariable(
826 L"MyVar",
827 &mFormSetGuid,
828 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
829 MyVarSize,
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 case 0x1111:
874 //
875 // EfiVarstore question takes sample action (print value as debug information)
876 // after read/write question.
877 //
878 MyVarSize = 1;
879 Status = gRT->GetVariable(
880 L"MyVar",
881 &mFormSetGuid,
882 NULL,
883 &MyVarSize,
884 &MyVar
885 );
886 ASSERT_EFI_ERROR (Status);
887 DEBUG ((DEBUG_INFO, "EfiVarstore question: Tall value is %d with value width %d\n", MyVar, MyVarSize));
888 default:
889 break;
890 }
891
892 return Status;
893 }
894
895 /**
896 Main entry for this driver.
897
898 @param ImageHandle Image handle this driver.
899 @param SystemTable Pointer to SystemTable.
900
901 @retval EFI_SUCESS This function always complete successfully.
902
903 **/
904 EFI_STATUS
905 EFIAPI
906 DriverSampleInit (
907 IN EFI_HANDLE ImageHandle,
908 IN EFI_SYSTEM_TABLE *SystemTable
909 )
910 {
911 EFI_STATUS Status;
912 EFI_HII_HANDLE HiiHandle[2];
913 EFI_SCREEN_DESCRIPTOR Screen;
914 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
915 EFI_HII_STRING_PROTOCOL *HiiString;
916 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
917 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
918 CHAR16 *NewString;
919 UINTN BufferSize;
920 DRIVER_SAMPLE_CONFIGURATION *Configuration;
921 BOOLEAN ActionFlag;
922 EFI_STRING ConfigRequestHdr;
923
924 //
925 // Initialize the local variables.
926 //
927 ConfigRequestHdr = NULL;
928 //
929 // Initialize screen dimensions for SendForm().
930 // Remove 3 characters from top and bottom
931 //
932 ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
933 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
934
935 Screen.TopRow = 3;
936 Screen.BottomRow = Screen.BottomRow - 3;
937
938 //
939 // Initialize driver private data
940 //
941 PrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
942 if (PrivateData == NULL) {
943 return EFI_OUT_OF_RESOURCES;
944 }
945
946 PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
947
948 PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
949 PrivateData->ConfigAccess.RouteConfig = RouteConfig;
950 PrivateData->ConfigAccess.Callback = DriverCallback;
951 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
952
953 //
954 // Locate Hii Database protocol
955 //
956 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
957 if (EFI_ERROR (Status)) {
958 return Status;
959 }
960 PrivateData->HiiDatabase = HiiDatabase;
961
962 //
963 // Locate HiiString protocol
964 //
965 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
966 if (EFI_ERROR (Status)) {
967 return Status;
968 }
969 PrivateData->HiiString = HiiString;
970
971 //
972 // Locate Formbrowser2 protocol
973 //
974 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
975 if (EFI_ERROR (Status)) {
976 return Status;
977 }
978 PrivateData->FormBrowser2 = FormBrowser2;
979
980 //
981 // Locate ConfigRouting protocol
982 //
983 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
984 if (EFI_ERROR (Status)) {
985 return Status;
986 }
987 PrivateData->HiiConfigRouting = HiiConfigRouting;
988
989 Status = gBS->InstallMultipleProtocolInterfaces (
990 &DriverHandle[0],
991 &gEfiDevicePathProtocolGuid,
992 &mHiiVendorDevicePath0,
993 &gEfiHiiConfigAccessProtocolGuid,
994 &PrivateData->ConfigAccess,
995 NULL
996 );
997 ASSERT_EFI_ERROR (Status);
998
999 PrivateData->DriverHandle[0] = DriverHandle[0];
1000
1001 //
1002 // Publish our HII data
1003 //
1004 HiiHandle[0] = HiiAddPackages (
1005 &mFormSetGuid,
1006 DriverHandle[0],
1007 DriverSampleStrings,
1008 VfrBin,
1009 NULL
1010 );
1011 if (HiiHandle[0] == NULL) {
1012 return EFI_OUT_OF_RESOURCES;
1013 }
1014
1015 PrivateData->HiiHandle[0] = HiiHandle[0];
1016
1017 //
1018 // Publish another Fromset
1019 //
1020 Status = gBS->InstallMultipleProtocolInterfaces (
1021 &DriverHandle[1],
1022 &gEfiDevicePathProtocolGuid,
1023 &mHiiVendorDevicePath1,
1024 NULL
1025 );
1026 ASSERT_EFI_ERROR (Status);
1027
1028 PrivateData->DriverHandle[1] = DriverHandle[1];
1029
1030 HiiHandle[1] = HiiAddPackages (
1031 &mInventoryGuid,
1032 DriverHandle[1],
1033 DriverSampleStrings,
1034 InventoryBin,
1035 NULL
1036 );
1037 if (HiiHandle[1] == NULL) {
1038 return EFI_OUT_OF_RESOURCES;
1039 }
1040
1041 PrivateData->HiiHandle[1] = HiiHandle[1];
1042
1043 //
1044 // Very simple example of how one would update a string that is already
1045 // in the HII database
1046 //
1047 NewString = L"700 Mhz";
1048
1049 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
1050 return EFI_OUT_OF_RESOURCES;
1051 }
1052
1053 //
1054 // Initialize configuration data
1055 //
1056 Configuration = &PrivateData->Configuration;
1057 ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
1058
1059 //
1060 // Try to read NV config EFI variable first
1061 //
1062 ConfigRequestHdr = HiiConstructConfigHdr (&mFormSetGuid, VariableName, DriverHandle[0]);
1063 ASSERT (ConfigRequestHdr != NULL);
1064
1065 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1066 Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);
1067 if (EFI_ERROR (Status)) {
1068 //
1069 // Store zero data Buffer Storage to EFI variable
1070 //
1071 Status = gRT->SetVariable(
1072 VariableName,
1073 &mFormSetGuid,
1074 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1075 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1076 Configuration
1077 );
1078 ASSERT (Status == EFI_SUCCESS);
1079 //
1080 // EFI variable for NV config doesn't exit, we should build this variable
1081 // based on default values stored in IFR
1082 //
1083 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
1084 ASSERT (ActionFlag);
1085 } else {
1086 //
1087 // EFI variable does exist and Validate Current Setting
1088 //
1089 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
1090 ASSERT (ActionFlag);
1091 }
1092
1093 FreePool (ConfigRequestHdr);
1094
1095
1096 //
1097 // In default, this driver is built into Flash device image,
1098 // the following code doesn't run.
1099 //
1100
1101 //
1102 // Example of how to display only the item we sent to HII
1103 // When this driver is not built into Flash device image,
1104 // it need to call SendForm to show front page by itself.
1105 //
1106 if (DISPLAY_ONLY_MY_ITEM <= 1) {
1107 //
1108 // Have the browser pull out our copy of the data, and only display our data
1109 //
1110 Status = FormBrowser2->SendForm (
1111 FormBrowser2,
1112 &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
1113 1,
1114 NULL,
1115 0,
1116 NULL,
1117 NULL
1118 );
1119
1120 HiiRemovePackages (HiiHandle[0]);
1121
1122 HiiRemovePackages (HiiHandle[1]);
1123 }
1124
1125 return EFI_SUCCESS;
1126 }
1127
1128 /**
1129 Unloads the application and its installed protocol.
1130
1131 @param[in] ImageHandle Handle that identifies the image to be unloaded.
1132
1133 @retval EFI_SUCCESS The image has been unloaded.
1134 **/
1135 EFI_STATUS
1136 EFIAPI
1137 DriverSampleUnload (
1138 IN EFI_HANDLE ImageHandle
1139 )
1140 {
1141 if (DriverHandle[0] != NULL) {
1142 gBS->UninstallMultipleProtocolInterfaces (
1143 DriverHandle[0],
1144 &gEfiDevicePathProtocolGuid,
1145 &mHiiVendorDevicePath0,
1146 &gEfiHiiConfigAccessProtocolGuid,
1147 &PrivateData->ConfigAccess,
1148 NULL
1149 );
1150 DriverHandle[0] = NULL;
1151 }
1152
1153 if (DriverHandle[1] != NULL) {
1154 gBS->UninstallMultipleProtocolInterfaces (
1155 DriverHandle[1],
1156 &gEfiDevicePathProtocolGuid,
1157 &mHiiVendorDevicePath1,
1158 NULL
1159 );
1160 DriverHandle[1] = NULL;
1161 }
1162
1163 if (PrivateData->HiiHandle[0] != NULL) {
1164 HiiRemovePackages (PrivateData->HiiHandle[0]);
1165 }
1166
1167 if (PrivateData->HiiHandle[1] != NULL) {
1168 HiiRemovePackages (PrivateData->HiiHandle[1]);
1169 }
1170
1171 if (PrivateData != NULL) {
1172 FreePool (PrivateData);
1173 PrivateData = NULL;
1174 }
1175
1176 return EFI_SUCCESS;
1177 }