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