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