]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
9c5d4bb61e7d82e1988a73c277e875e0d897f978
[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 - 2016, Intel Corporation. All rights reserved.<BR>
6 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 CHAR16 VariableName[] = L"MyIfrNVData";
22 CHAR16 MyEfiVar[] = L"MyEfiVar";
23 EFI_HANDLE DriverHandle[2] = {NULL, NULL};
24 DRIVER_SAMPLE_PRIVATE_DATA *mPrivateData = NULL;
25 EFI_EVENT mEvent;
26
27 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath0 = {
28 {
29 {
30 HARDWARE_DEVICE_PATH,
31 HW_VENDOR_DP,
32 {
33 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
34 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
35 }
36 },
37 DRIVER_SAMPLE_FORMSET_GUID
38 },
39 {
40 END_DEVICE_PATH_TYPE,
41 END_ENTIRE_DEVICE_PATH_SUBTYPE,
42 {
43 (UINT8) (END_DEVICE_PATH_LENGTH),
44 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
45 }
46 }
47 };
48
49 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath1 = {
50 {
51 {
52 HARDWARE_DEVICE_PATH,
53 HW_VENDOR_DP,
54 {
55 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
56 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
57 }
58 },
59 DRIVER_SAMPLE_INVENTORY_GUID
60 },
61 {
62 END_DEVICE_PATH_TYPE,
63 END_ENTIRE_DEVICE_PATH_SUBTYPE,
64 {
65 (UINT8) (END_DEVICE_PATH_LENGTH),
66 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
67 }
68 }
69 };
70
71 /**
72 Set value of a data element in an Array by its Index.
73
74 @param Array The data array.
75 @param Type Type of the data in this array.
76 @param Index Zero based index for data in this array.
77 @param Value The value to be set.
78
79 **/
80 VOID
81 SetArrayData (
82 IN VOID *Array,
83 IN UINT8 Type,
84 IN UINTN Index,
85 IN UINT64 Value
86 )
87 {
88
89 ASSERT (Array != NULL);
90
91 switch (Type) {
92 case EFI_IFR_TYPE_NUM_SIZE_8:
93 *(((UINT8 *) Array) + Index) = (UINT8) Value;
94 break;
95
96 case EFI_IFR_TYPE_NUM_SIZE_16:
97 *(((UINT16 *) Array) + Index) = (UINT16) Value;
98 break;
99
100 case EFI_IFR_TYPE_NUM_SIZE_32:
101 *(((UINT32 *) Array) + Index) = (UINT32) Value;
102 break;
103
104 case EFI_IFR_TYPE_NUM_SIZE_64:
105 *(((UINT64 *) Array) + Index) = (UINT64) Value;
106 break;
107
108 default:
109 break;
110 }
111 }
112
113 /**
114 Add empty function for event process function.
115
116 @param Event The Event need to be process
117 @param Context The context of the event.
118
119 **/
120 VOID
121 EFIAPI
122 DriverSampleInternalEmptyFunction (
123 IN EFI_EVENT Event,
124 IN VOID *Context
125 )
126 {
127 }
128
129 /**
130 Notification function for keystrokes.
131
132 @param[in] KeyData The key that was pressed.
133
134 @retval EFI_SUCCESS The operation was successful.
135 **/
136 EFI_STATUS
137 EFIAPI
138 NotificationFunction(
139 IN EFI_KEY_DATA *KeyData
140 )
141 {
142 gBS->SignalEvent (mEvent);
143
144 return EFI_SUCCESS;
145 }
146
147 /**
148 Function to start monitoring for CTRL-C using SimpleTextInputEx.
149
150 @retval EFI_SUCCESS The feature is enabled.
151 @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
152 **/
153 EFI_STATUS
154 EFIAPI
155 InternalStartMonitor(
156 VOID
157 )
158 {
159 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
160 EFI_KEY_DATA KeyData;
161 EFI_STATUS Status;
162 EFI_HANDLE *Handles;
163 UINTN HandleCount;
164 UINTN HandleIndex;
165 EFI_HANDLE NotifyHandle;
166
167 Status = gBS->LocateHandleBuffer (
168 ByProtocol,
169 &gEfiSimpleTextInputExProtocolGuid,
170 NULL,
171 &HandleCount,
172 &Handles
173 );
174 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
175 Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &SimpleEx);
176 ASSERT_EFI_ERROR (Status);
177
178 KeyData.KeyState.KeyToggleState = 0;
179 KeyData.Key.ScanCode = 0;
180 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
181 KeyData.Key.UnicodeChar = L'c';
182
183 Status = SimpleEx->RegisterKeyNotify(
184 SimpleEx,
185 &KeyData,
186 NotificationFunction,
187 &NotifyHandle);
188 if (EFI_ERROR (Status)) {
189 break;
190 }
191
192 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
193 Status = SimpleEx->RegisterKeyNotify(
194 SimpleEx,
195 &KeyData,
196 NotificationFunction,
197 &NotifyHandle);
198 if (EFI_ERROR (Status)) {
199 break;
200 }
201 }
202
203 return EFI_SUCCESS;
204 }
205
206 /**
207 Function to stop monitoring for CTRL-C using SimpleTextInputEx.
208
209 @retval EFI_SUCCESS The feature is enabled.
210 @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
211 **/
212 EFI_STATUS
213 EFIAPI
214 InternalStopMonitor(
215 VOID
216 )
217 {
218 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
219 EFI_STATUS Status;
220 EFI_HANDLE *Handles;
221 EFI_KEY_DATA KeyData;
222 UINTN HandleCount;
223 UINTN HandleIndex;
224 EFI_HANDLE NotifyHandle;
225
226 Status = gBS->LocateHandleBuffer (
227 ByProtocol,
228 &gEfiSimpleTextInputExProtocolGuid,
229 NULL,
230 &HandleCount,
231 &Handles
232 );
233 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
234 Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &SimpleEx);
235 ASSERT_EFI_ERROR (Status);
236
237 KeyData.KeyState.KeyToggleState = 0;
238 KeyData.Key.ScanCode = 0;
239 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
240 KeyData.Key.UnicodeChar = L'c';
241
242 Status = SimpleEx->RegisterKeyNotify(
243 SimpleEx,
244 &KeyData,
245 NotificationFunction,
246 &NotifyHandle);
247 if (!EFI_ERROR (Status)) {
248 Status = SimpleEx->UnregisterKeyNotify (SimpleEx, NotifyHandle);
249 }
250
251 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
252 Status = SimpleEx->RegisterKeyNotify(
253 SimpleEx,
254 &KeyData,
255 NotificationFunction,
256 &NotifyHandle);
257 if (!EFI_ERROR (Status)) {
258 Status = SimpleEx->UnregisterKeyNotify (SimpleEx, NotifyHandle);
259 }
260 }
261 return EFI_SUCCESS;
262 }
263
264
265 /**
266 Encode the password using a simple algorithm.
267
268 @param Password The string to be encoded.
269 @param MaxSize The size of the string.
270
271 **/
272 VOID
273 EncodePassword (
274 IN CHAR16 *Password,
275 IN UINTN MaxSize
276 )
277 {
278 UINTN Index;
279 UINTN Loop;
280 CHAR16 *Buffer;
281 CHAR16 *Key;
282
283 Key = L"MAR10648567";
284 Buffer = AllocateZeroPool (MaxSize);
285 ASSERT (Buffer != NULL);
286
287 for (Index = 0; Key[Index] != 0; Index++) {
288 for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {
289 Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);
290 }
291 }
292
293 CopyMem (Password, Buffer, MaxSize);
294
295 FreePool (Buffer);
296 return ;
297 }
298
299 /**
300 Validate the user's password.
301
302 @param PrivateData This driver's private context data.
303 @param StringId The user's input.
304
305 @retval EFI_SUCCESS The user's input matches the password.
306 @retval EFI_NOT_READY The user's input does not match the password.
307 **/
308 EFI_STATUS
309 ValidatePassword (
310 IN DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,
311 IN EFI_STRING_ID StringId
312 )
313 {
314 EFI_STATUS Status;
315 UINTN Index;
316 UINTN BufferSize;
317 UINTN PasswordMaxSize;
318 CHAR16 *Password;
319 CHAR16 *EncodedPassword;
320 BOOLEAN OldPassword;
321
322 //
323 // Get encoded password first
324 //
325 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
326 Status = gRT->GetVariable (
327 VariableName,
328 &gDriverSampleFormSetGuid,
329 NULL,
330 &BufferSize,
331 &PrivateData->Configuration
332 );
333 if (EFI_ERROR (Status)) {
334 //
335 // Old password not exist, prompt for new password
336 //
337 return EFI_SUCCESS;
338 }
339
340 OldPassword = FALSE;
341 PasswordMaxSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);
342 //
343 // Check whether we have any old password set
344 //
345 for (Index = 0; Index < PasswordMaxSize / sizeof (UINT16); Index++) {
346 if (PrivateData->Configuration.WhatIsThePassword2[Index] != 0) {
347 OldPassword = TRUE;
348 break;
349 }
350 }
351 if (!OldPassword) {
352 //
353 // Old password not exist, return EFI_SUCCESS to prompt for new password
354 //
355 return EFI_SUCCESS;
356 }
357
358 //
359 // Get user input password
360 //
361 Password = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);
362 if (Password == NULL) {
363 return EFI_NOT_READY;
364 }
365 if (StrSize (Password) > PasswordMaxSize) {
366 FreePool (Password);
367 return EFI_NOT_READY;
368 }
369
370 //
371 // Validate old password
372 //
373 EncodedPassword = AllocateZeroPool (PasswordMaxSize);
374 ASSERT (EncodedPassword != NULL);
375 StrnCpyS (EncodedPassword, PasswordMaxSize / sizeof (CHAR16), Password, StrLen (Password));
376 EncodePassword (EncodedPassword, StrLen (EncodedPassword) * sizeof (CHAR16));
377 if (CompareMem (EncodedPassword, PrivateData->Configuration.WhatIsThePassword2, PasswordMaxSize) != 0) {
378 //
379 // Old password mismatch, return EFI_NOT_READY to prompt for error message
380 //
381 Status = EFI_NOT_READY;
382 } else {
383 Status = EFI_SUCCESS;
384 }
385
386 FreePool (Password);
387 FreePool (EncodedPassword);
388
389 return Status;
390 }
391
392 /**
393 Encode the password using a simple algorithm.
394
395 @param PrivateData This driver's private context data.
396 @param StringId The password from User.
397
398 @retval EFI_SUCESS The operation is successful.
399 @return Other value if gRT->SetVariable () fails.
400
401 **/
402 EFI_STATUS
403 SetPassword (
404 IN DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,
405 IN EFI_STRING_ID StringId
406 )
407 {
408 EFI_STATUS Status;
409 CHAR16 *Password;
410 CHAR16 *TempPassword;
411 UINTN PasswordSize;
412 DRIVER_SAMPLE_CONFIGURATION *Configuration;
413 UINTN BufferSize;
414
415 //
416 // Get Buffer Storage data from EFI variable
417 //
418 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
419 Status = gRT->GetVariable (
420 VariableName,
421 &gDriverSampleFormSetGuid,
422 NULL,
423 &BufferSize,
424 &PrivateData->Configuration
425 );
426 if (EFI_ERROR (Status)) {
427 return Status;
428 }
429
430 //
431 // Get user input password
432 //
433 Password = PrivateData->Configuration.WhatIsThePassword2;
434 PasswordSize = sizeof (PrivateData->Configuration.WhatIsThePassword2);
435 ZeroMem (Password, PasswordSize);
436
437 TempPassword = HiiGetString (PrivateData->HiiHandle[0], StringId, NULL);
438 if (TempPassword == NULL) {
439 return EFI_NOT_READY;
440 }
441 if (StrSize (TempPassword) > PasswordSize) {
442 FreePool (TempPassword);
443 return EFI_NOT_READY;
444 }
445 StrnCpyS (Password, PasswordSize / sizeof (CHAR16), TempPassword, StrLen (TempPassword));
446 FreePool (TempPassword);
447
448 //
449 // Retrive uncommitted data from Browser
450 //
451 Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
452 ASSERT (Configuration != NULL);
453 if (HiiGetBrowserData (&gDriverSampleFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
454 //
455 // Update password's clear text in the screen
456 //
457 CopyMem (Configuration->PasswordClearText, Password, StrSize (Password));
458
459 //
460 // Update uncommitted data of Browser
461 //
462 HiiSetBrowserData (
463 &gDriverSampleFormSetGuid,
464 VariableName,
465 sizeof (DRIVER_SAMPLE_CONFIGURATION),
466 (UINT8 *) Configuration,
467 NULL
468 );
469 }
470
471 //
472 // Free Configuration Buffer
473 //
474 FreePool (Configuration);
475
476
477 //
478 // Set password
479 //
480 EncodePassword (Password, StrLen (Password) * 2);
481 Status = gRT->SetVariable(
482 VariableName,
483 &gDriverSampleFormSetGuid,
484 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
485 sizeof (DRIVER_SAMPLE_CONFIGURATION),
486 &PrivateData->Configuration
487 );
488 return Status;
489 }
490
491 /**
492 Update names of Name/Value storage to current language.
493
494 @param PrivateData Points to the driver private data.
495
496 @retval EFI_SUCCESS All names are successfully updated.
497 @retval EFI_NOT_FOUND Failed to get Name from HII database.
498
499 **/
500 EFI_STATUS
501 LoadNameValueNames (
502 IN DRIVER_SAMPLE_PRIVATE_DATA *PrivateData
503 )
504 {
505 UINTN Index;
506
507 //
508 // Get Name/Value name string of current language
509 //
510 for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {
511 PrivateData->NameValueName[Index] = HiiGetString (
512 PrivateData->HiiHandle[0],
513 PrivateData->NameStringId[Index],
514 NULL
515 );
516 if (PrivateData->NameValueName[Index] == NULL) {
517 return EFI_NOT_FOUND;
518 }
519 }
520
521 return EFI_SUCCESS;
522 }
523
524
525 /**
526 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
527 or WIDTH or VALUE.
528 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
529
530 This is a internal function.
531
532 @param StringPtr String in <BlockConfig> format and points to the
533 first character of <Number>.
534 @param Number The output value. Caller takes the responsibility
535 to free memory.
536 @param Len Length of the <Number>, in characters.
537
538 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
539 structures.
540 @retval EFI_SUCCESS Value of <Number> is outputted in Number
541 successfully.
542
543 **/
544 EFI_STATUS
545 GetValueOfNumber (
546 IN EFI_STRING StringPtr,
547 OUT UINT8 **Number,
548 OUT UINTN *Len
549 )
550 {
551 EFI_STRING TmpPtr;
552 UINTN Length;
553 EFI_STRING Str;
554 UINT8 *Buf;
555 EFI_STATUS Status;
556 UINT8 DigitUint8;
557 UINTN Index;
558 CHAR16 TemStr[2];
559
560 if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
561 return EFI_INVALID_PARAMETER;
562 }
563
564 Buf = NULL;
565
566 TmpPtr = StringPtr;
567 while (*StringPtr != L'\0' && *StringPtr != L'&') {
568 StringPtr++;
569 }
570 *Len = StringPtr - TmpPtr;
571 Length = *Len + 1;
572
573 Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
574 if (Str == NULL) {
575 Status = EFI_OUT_OF_RESOURCES;
576 goto Exit;
577 }
578 CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
579 *(Str + *Len) = L'\0';
580
581 Length = (Length + 1) / 2;
582 Buf = (UINT8 *) AllocateZeroPool (Length);
583 if (Buf == NULL) {
584 Status = EFI_OUT_OF_RESOURCES;
585 goto Exit;
586 }
587
588 Length = *Len;
589 ZeroMem (TemStr, sizeof (TemStr));
590 for (Index = 0; Index < Length; Index ++) {
591 TemStr[0] = Str[Length - Index - 1];
592 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
593 if ((Index & 1) == 0) {
594 Buf [Index/2] = DigitUint8;
595 } else {
596 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
597 }
598 }
599
600 *Number = Buf;
601 Status = EFI_SUCCESS;
602
603 Exit:
604 if (Str != NULL) {
605 FreePool (Str);
606 }
607
608 return Status;
609 }
610
611 /**
612 Create altcfg string.
613
614 @param Result The request result string.
615 @param ConfigHdr The request head info. <ConfigHdr> format.
616 @param Offset The offset of the parameter int he structure.
617 @param Width The width of the parameter.
618
619
620 @retval The string with altcfg info append at the end.
621 **/
622 EFI_STRING
623 CreateAltCfgString (
624 IN EFI_STRING Result,
625 IN EFI_STRING ConfigHdr,
626 IN UINTN Offset,
627 IN UINTN Width
628 )
629 {
630 EFI_STRING StringPtr;
631 EFI_STRING TmpStr;
632 UINTN NewLen;
633
634 NewLen = StrLen (Result);
635 //
636 // String Len = ConfigResp + AltConfig + AltConfig + 1("\0")
637 //
638 NewLen = (NewLen + ((1 + StrLen (ConfigHdr) + 8 + 4) + (8 + 4 + 7 + 4 + 7 + 4)) * 2 + 1) * sizeof (CHAR16);
639 StringPtr = AllocateZeroPool (NewLen);
640 if (StringPtr == NULL) {
641 return NULL;
642 }
643
644 TmpStr = StringPtr;
645 if (Result != NULL) {
646 StrCpyS (StringPtr, NewLen / sizeof (CHAR16), Result);
647 StringPtr += StrLen (Result);
648 FreePool (Result);
649 }
650
651 UnicodeSPrint (
652 StringPtr,
653 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
654 L"&%s&ALTCFG=%04x",
655 ConfigHdr,
656 EFI_HII_DEFAULT_CLASS_STANDARD
657 );
658 StringPtr += StrLen (StringPtr);
659
660 UnicodeSPrint (
661 StringPtr,
662 (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
663 L"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
664 Offset,
665 Width,
666 DEFAULT_CLASS_STANDARD_VALUE
667 );
668 StringPtr += StrLen (StringPtr);
669
670 UnicodeSPrint (
671 StringPtr,
672 (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
673 L"&%s&ALTCFG=%04x",
674 ConfigHdr,
675 EFI_HII_DEFAULT_CLASS_MANUFACTURING
676 );
677 StringPtr += StrLen (StringPtr);
678
679 UnicodeSPrint (
680 StringPtr,
681 (8 + 4 + 7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
682 L"&OFFSET=%04x&WIDTH=%04x&VALUE=%04x",
683 Offset,
684 Width,
685 DEFAULT_CLASS_MANUFACTURING_VALUE
686 );
687 StringPtr += StrLen (StringPtr);
688
689 return TmpStr;
690 }
691
692 /**
693 Check whether need to add the altcfg string. if need to add, add the altcfg
694 string.
695
696 @param RequestResult The request result string.
697 @param ConfigRequestHdr The request head info. <ConfigHdr> format.
698
699 **/
700 VOID
701 AppendAltCfgString (
702 IN OUT EFI_STRING *RequestResult,
703 IN EFI_STRING ConfigRequestHdr
704 )
705 {
706 EFI_STRING StringPtr;
707 UINTN Length;
708 UINT8 *TmpBuffer;
709 UINTN Offset;
710 UINTN Width;
711 UINTN BlockSize;
712 UINTN ValueOffset;
713 UINTN ValueWidth;
714 EFI_STATUS Status;
715
716 TmpBuffer = NULL;
717 StringPtr = *RequestResult;
718 StringPtr = StrStr (StringPtr, L"OFFSET");
719 BlockSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
720 ValueOffset = OFFSET_OF (DRIVER_SAMPLE_CONFIGURATION, GetDefaultValueFromAccess);
721 ValueWidth = sizeof (((DRIVER_SAMPLE_CONFIGURATION *)0)->GetDefaultValueFromAccess);
722
723 if (StringPtr == NULL) {
724 return;
725 }
726
727 while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
728 StringPtr += StrLen (L"OFFSET=");
729 //
730 // Get Offset
731 //
732 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
733 if (EFI_ERROR (Status)) {
734 return;
735 }
736 Offset = 0;
737 CopyMem (
738 &Offset,
739 TmpBuffer,
740 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
741 );
742 FreePool (TmpBuffer);
743
744 StringPtr += Length;
745 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
746 return;
747 }
748 StringPtr += StrLen (L"&WIDTH=");
749
750 //
751 // Get Width
752 //
753 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
754 if (EFI_ERROR (Status)) {
755 return;
756 }
757 Width = 0;
758 CopyMem (
759 &Width,
760 TmpBuffer,
761 (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
762 );
763 FreePool (TmpBuffer);
764
765 StringPtr += Length;
766 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
767 return;
768 }
769 StringPtr += StrLen (L"&VALUE=");
770
771 //
772 // Get Value
773 //
774 Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
775 if (EFI_ERROR (Status)) {
776 return;
777 }
778 StringPtr += Length;
779
780 //
781 // Calculate Value and convert it to hex string.
782 //
783 if (Offset + Width > BlockSize) {
784 return;
785 }
786
787 if (Offset <= ValueOffset && Offset + Width >= ValueOffset + ValueWidth) {
788 *RequestResult = CreateAltCfgString(*RequestResult, ConfigRequestHdr, ValueOffset, ValueWidth);
789 return;
790 }
791 }
792 }
793
794 /**
795 This function allows a caller to extract the current configuration for one
796 or more named elements from the target driver.
797
798 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
799 @param Request A null-terminated Unicode string in
800 <ConfigRequest> format.
801 @param Progress On return, points to a character in the Request
802 string. Points to the string's null terminator if
803 request was successful. Points to the most recent
804 '&' before the first failing name/value pair (or
805 the beginning of the string if the failure is in
806 the first name/value pair) if the request was not
807 successful.
808 @param Results A null-terminated Unicode string in
809 <ConfigAltResp> format which has all values filled
810 in for the names in the Request string. String to
811 be allocated by the called function.
812
813 @retval EFI_SUCCESS The Results is filled with the requested values.
814 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
815 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
816 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
817 driver.
818
819 **/
820 EFI_STATUS
821 EFIAPI
822 ExtractConfig (
823 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
824 IN CONST EFI_STRING Request,
825 OUT EFI_STRING *Progress,
826 OUT EFI_STRING *Results
827 )
828 {
829 EFI_STATUS Status;
830 UINTN BufferSize;
831 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
832 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
833 EFI_STRING ConfigRequest;
834 EFI_STRING ConfigRequestHdr;
835 UINTN Size;
836 EFI_STRING Value;
837 UINTN ValueStrLen;
838 CHAR16 BackupChar;
839 CHAR16 *StrPointer;
840 BOOLEAN AllocatedRequest;
841
842 if (Progress == NULL || Results == NULL) {
843 return EFI_INVALID_PARAMETER;
844 }
845 //
846 // Initialize the local variables.
847 //
848 ConfigRequestHdr = NULL;
849 ConfigRequest = NULL;
850 Size = 0;
851 *Progress = Request;
852 AllocatedRequest = FALSE;
853
854 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
855 HiiConfigRouting = PrivateData->HiiConfigRouting;
856
857 //
858 // Get Buffer Storage data from EFI variable.
859 // Try to get the current setting from variable.
860 //
861 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
862 Status = gRT->GetVariable (
863 VariableName,
864 &gDriverSampleFormSetGuid,
865 NULL,
866 &BufferSize,
867 &PrivateData->Configuration
868 );
869 if (EFI_ERROR (Status)) {
870 return EFI_NOT_FOUND;
871 }
872
873 if (Request == NULL) {
874 //
875 // Request is set to NULL, construct full request string.
876 //
877
878 //
879 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
880 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
881 //
882 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, PrivateData->DriverHandle[0]);
883 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
884 ConfigRequest = AllocateZeroPool (Size);
885 ASSERT (ConfigRequest != NULL);
886 AllocatedRequest = TRUE;
887 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
888 FreePool (ConfigRequestHdr);
889 ConfigRequestHdr = NULL;
890 } else {
891 //
892 // Check routing data in <ConfigHdr>.
893 // Note: if only one Storage is used, then this checking could be skipped.
894 //
895 if (!HiiIsConfigHdrMatch (Request, &gDriverSampleFormSetGuid, NULL)) {
896 return EFI_NOT_FOUND;
897 }
898 //
899 // Check whether request for EFI Varstore. EFI varstore get data
900 // through hii database, not support in this path.
901 //
902 if (HiiIsConfigHdrMatch(Request, &gDriverSampleFormSetGuid, MyEfiVar)) {
903 return EFI_UNSUPPORTED;
904 }
905 //
906 // Set Request to the unified request string.
907 //
908 ConfigRequest = Request;
909 //
910 // Check whether Request includes Request Element.
911 //
912 if (StrStr (Request, L"OFFSET") == NULL) {
913 //
914 // Check Request Element does exist in Reques String
915 //
916 StrPointer = StrStr (Request, L"PATH");
917 if (StrPointer == NULL) {
918 return EFI_INVALID_PARAMETER;
919 }
920 if (StrStr (StrPointer, L"&") == NULL) {
921 Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);
922 ConfigRequest = AllocateZeroPool (Size);
923 ASSERT (ConfigRequest != NULL);
924 AllocatedRequest = TRUE;
925 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", Request, (UINT64)BufferSize);
926 }
927 }
928 }
929
930 //
931 // Check if requesting Name/Value storage
932 //
933 if (StrStr (ConfigRequest, L"OFFSET") == NULL) {
934 //
935 // Update Name/Value storage Names
936 //
937 Status = LoadNameValueNames (PrivateData);
938 if (EFI_ERROR (Status)) {
939 return Status;
940 }
941
942 //
943 // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"
944 // <Request> ::=<ConfigHdr>&Name0&Name1&Name2
945 // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044
946 //
947 BufferSize = (StrLen (ConfigRequest) +
948 1 + sizeof (PrivateData->Configuration.NameValueVar0) * 2 +
949 1 + sizeof (PrivateData->Configuration.NameValueVar1) * 2 +
950 1 + sizeof (PrivateData->Configuration.NameValueVar2) * 2 + 1) * sizeof (CHAR16);
951 *Results = AllocateZeroPool (BufferSize);
952 ASSERT (*Results != NULL);
953 StrCpyS (*Results, BufferSize / sizeof (CHAR16), ConfigRequest);
954 Value = *Results;
955
956 //
957 // Append value of NameValueVar0, type is UINT8
958 //
959 if ((Value = StrStr (*Results, PrivateData->NameValueName[0])) != NULL) {
960 Value += StrLen (PrivateData->NameValueName[0]);
961 ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar0) * 2) + 1);
962 CopyMem (Value + ValueStrLen, Value, StrSize (Value));
963
964 BackupChar = Value[ValueStrLen];
965 *Value++ = L'=';
966 Value += UnicodeValueToString (
967 Value,
968 PREFIX_ZERO | RADIX_HEX,
969 PrivateData->Configuration.NameValueVar0,
970 sizeof (PrivateData->Configuration.NameValueVar0) * 2
971 );
972 *Value = BackupChar;
973 }
974
975 //
976 // Append value of NameValueVar1, type is UINT16
977 //
978 if ((Value = StrStr (*Results, PrivateData->NameValueName[1])) != NULL) {
979 Value += StrLen (PrivateData->NameValueName[1]);
980 ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar1) * 2) + 1);
981 CopyMem (Value + ValueStrLen, Value, StrSize (Value));
982
983 BackupChar = Value[ValueStrLen];
984 *Value++ = L'=';
985 Value += UnicodeValueToString (
986 Value,
987 PREFIX_ZERO | RADIX_HEX,
988 PrivateData->Configuration.NameValueVar1,
989 sizeof (PrivateData->Configuration.NameValueVar1) * 2
990 );
991 *Value = BackupChar;
992 }
993
994 //
995 // Append value of NameValueVar2, type is CHAR16 *
996 //
997 if ((Value = StrStr (*Results, PrivateData->NameValueName[2])) != NULL) {
998 Value += StrLen (PrivateData->NameValueName[2]);
999 ValueStrLen = StrLen (PrivateData->Configuration.NameValueVar2) * 4 + 1;
1000 CopyMem (Value + ValueStrLen, Value, StrSize (Value));
1001
1002 *Value++ = L'=';
1003 //
1004 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1005 //
1006 StrPointer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;
1007 for (; *StrPointer != L'\0'; StrPointer++) {
1008 Value += UnicodeValueToString (Value, PREFIX_ZERO | RADIX_HEX, *StrPointer, 4);
1009 }
1010 }
1011
1012 Status = EFI_SUCCESS;
1013 } else {
1014 //
1015 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1016 //
1017 Status = HiiConfigRouting->BlockToConfig (
1018 HiiConfigRouting,
1019 ConfigRequest,
1020 (UINT8 *) &PrivateData->Configuration,
1021 BufferSize,
1022 Results,
1023 Progress
1024 );
1025 if (!EFI_ERROR (Status)) {
1026 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, PrivateData->DriverHandle[0]);
1027 AppendAltCfgString(Results, ConfigRequestHdr);
1028 }
1029 }
1030
1031 //
1032 // Free the allocated config request string.
1033 //
1034 if (AllocatedRequest) {
1035 FreePool (ConfigRequest);
1036 }
1037
1038 if (ConfigRequestHdr != NULL) {
1039 FreePool (ConfigRequestHdr);
1040 }
1041 //
1042 // Set Progress string to the original request string.
1043 //
1044 if (Request == NULL) {
1045 *Progress = NULL;
1046 } else if (StrStr (Request, L"OFFSET") == NULL) {
1047 *Progress = Request + StrLen (Request);
1048 }
1049
1050 return Status;
1051 }
1052
1053
1054 /**
1055 This function processes the results of changes in configuration.
1056
1057 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1058 @param Configuration A null-terminated Unicode string in <ConfigResp>
1059 format.
1060 @param Progress A pointer to a string filled in with the offset of
1061 the most recent '&' before the first failing
1062 name/value pair (or the beginning of the string if
1063 the failure is in the first name/value pair) or
1064 the terminating NULL if all was successful.
1065
1066 @retval EFI_SUCCESS The Results is processed successfully.
1067 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1068 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
1069 driver.
1070
1071 **/
1072 EFI_STATUS
1073 EFIAPI
1074 RouteConfig (
1075 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1076 IN CONST EFI_STRING Configuration,
1077 OUT EFI_STRING *Progress
1078 )
1079 {
1080 EFI_STATUS Status;
1081 UINTN BufferSize;
1082 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
1083 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1084 CHAR16 *Value;
1085 CHAR16 *StrPtr;
1086 CHAR16 TemStr[5];
1087 UINT8 *DataBuffer;
1088 UINT8 DigitUint8;
1089 UINTN Index;
1090 CHAR16 *StrBuffer;
1091
1092 if (Configuration == NULL || Progress == NULL) {
1093 return EFI_INVALID_PARAMETER;
1094 }
1095
1096 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1097 HiiConfigRouting = PrivateData->HiiConfigRouting;
1098 *Progress = Configuration;
1099
1100 //
1101 // Check routing data in <ConfigHdr>.
1102 // Note: if only one Storage is used, then this checking could be skipped.
1103 //
1104 if (!HiiIsConfigHdrMatch (Configuration, &gDriverSampleFormSetGuid, NULL)) {
1105 return EFI_NOT_FOUND;
1106 }
1107
1108 //
1109 // Check whether request for EFI Varstore. EFI varstore get data
1110 // through hii database, not support in this path.
1111 //
1112 if (HiiIsConfigHdrMatch(Configuration, &gDriverSampleFormSetGuid, MyEfiVar)) {
1113 return EFI_UNSUPPORTED;
1114 }
1115
1116 //
1117 // Get Buffer Storage data from EFI variable
1118 //
1119 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1120 Status = gRT->GetVariable (
1121 VariableName,
1122 &gDriverSampleFormSetGuid,
1123 NULL,
1124 &BufferSize,
1125 &PrivateData->Configuration
1126 );
1127 if (EFI_ERROR (Status)) {
1128 return Status;
1129 }
1130
1131 //
1132 // Check if configuring Name/Value storage
1133 //
1134 if (StrStr (Configuration, L"OFFSET") == NULL) {
1135 //
1136 // Update Name/Value storage Names
1137 //
1138 Status = LoadNameValueNames (PrivateData);
1139 if (EFI_ERROR (Status)) {
1140 return Status;
1141 }
1142
1143 //
1144 // Convert value for NameValueVar0
1145 //
1146 if ((Value = StrStr (Configuration, PrivateData->NameValueName[0])) != NULL) {
1147 //
1148 // Skip "Name="
1149 //
1150 Value += StrLen (PrivateData->NameValueName[0]);
1151 Value++;
1152 //
1153 // Get Value String
1154 //
1155 StrPtr = StrStr (Value, L"&");
1156 if (StrPtr == NULL) {
1157 StrPtr = Value + StrLen (Value);
1158 }
1159 //
1160 // Convert Value to Buffer data
1161 //
1162 DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar0;
1163 ZeroMem (TemStr, sizeof (TemStr));
1164 for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {
1165 TemStr[0] = *StrPtr;
1166 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
1167 if ((Index & 1) == 0) {
1168 DataBuffer [Index/2] = DigitUint8;
1169 } else {
1170 DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);
1171 }
1172 }
1173 }
1174
1175 //
1176 // Convert value for NameValueVar1
1177 //
1178 if ((Value = StrStr (Configuration, PrivateData->NameValueName[1])) != NULL) {
1179 //
1180 // Skip "Name="
1181 //
1182 Value += StrLen (PrivateData->NameValueName[1]);
1183 Value++;
1184 //
1185 // Get Value String
1186 //
1187 StrPtr = StrStr (Value, L"&");
1188 if (StrPtr == NULL) {
1189 StrPtr = Value + StrLen (Value);
1190 }
1191 //
1192 // Convert Value to Buffer data
1193 //
1194 DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar1;
1195 ZeroMem (TemStr, sizeof (TemStr));
1196 for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {
1197 TemStr[0] = *StrPtr;
1198 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
1199 if ((Index & 1) == 0) {
1200 DataBuffer [Index/2] = DigitUint8;
1201 } else {
1202 DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);
1203 }
1204 }
1205 }
1206
1207 //
1208 // Convert value for NameValueVar2
1209 //
1210 if ((Value = StrStr (Configuration, PrivateData->NameValueName[2])) != NULL) {
1211 //
1212 // Skip "Name="
1213 //
1214 Value += StrLen (PrivateData->NameValueName[2]);
1215 Value++;
1216 //
1217 // Get Value String
1218 //
1219 StrPtr = StrStr (Value, L"&");
1220 if (StrPtr == NULL) {
1221 StrPtr = Value + StrLen (Value);
1222 }
1223 //
1224 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1225 //
1226 StrBuffer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;
1227 ZeroMem (TemStr, sizeof (TemStr));
1228 while (Value < StrPtr) {
1229 StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value, 4);
1230 *(StrBuffer++) = (CHAR16) StrHexToUint64 (TemStr);
1231 Value += 4;
1232 }
1233 *StrBuffer = L'\0';
1234 }
1235
1236 //
1237 // Store Buffer Storage back to EFI variable
1238 //
1239 Status = gRT->SetVariable(
1240 VariableName,
1241 &gDriverSampleFormSetGuid,
1242 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1243 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1244 &PrivateData->Configuration
1245 );
1246
1247 return Status;
1248 }
1249
1250 //
1251 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
1252 //
1253 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1254 Status = HiiConfigRouting->ConfigToBlock (
1255 HiiConfigRouting,
1256 Configuration,
1257 (UINT8 *) &PrivateData->Configuration,
1258 &BufferSize,
1259 Progress
1260 );
1261 if (EFI_ERROR (Status)) {
1262 return Status;
1263 }
1264
1265 //
1266 // Store Buffer Storage back to EFI variable
1267 //
1268 Status = gRT->SetVariable(
1269 VariableName,
1270 &gDriverSampleFormSetGuid,
1271 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1272 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1273 &PrivateData->Configuration
1274 );
1275
1276 return Status;
1277 }
1278
1279
1280 /**
1281 This function processes the results of changes in configuration.
1282
1283 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1284 @param Action Specifies the type of action taken by the browser.
1285 @param QuestionId A unique value which is sent to the original
1286 exporting driver so that it can identify the type
1287 of data to expect.
1288 @param Type The type of value for the question.
1289 @param Value A pointer to the data being sent to the original
1290 exporting driver.
1291 @param ActionRequest On return, points to the action requested by the
1292 callback function.
1293
1294 @retval EFI_SUCCESS The callback successfully handled the action.
1295 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1296 variable and its data.
1297 @retval EFI_DEVICE_ERROR The variable could not be saved.
1298 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1299 callback.
1300
1301 **/
1302 EFI_STATUS
1303 EFIAPI
1304 DriverCallback (
1305 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1306 IN EFI_BROWSER_ACTION Action,
1307 IN EFI_QUESTION_ID QuestionId,
1308 IN UINT8 Type,
1309 IN EFI_IFR_TYPE_VALUE *Value,
1310 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1311 )
1312 {
1313 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
1314 EFI_STATUS Status;
1315 VOID *StartOpCodeHandle;
1316 VOID *OptionsOpCodeHandle;
1317 EFI_IFR_GUID_LABEL *StartLabel;
1318 VOID *EndOpCodeHandle;
1319 EFI_IFR_GUID_LABEL *EndLabel;
1320 EFI_INPUT_KEY Key;
1321 DRIVER_SAMPLE_CONFIGURATION *Configuration;
1322 MY_EFI_VARSTORE_DATA *EfiData;
1323 EFI_FORM_ID FormId;
1324 EFI_STRING Progress;
1325 EFI_STRING Results;
1326 UINT32 ProgressErr;
1327 CHAR16 *TmpStr;
1328 UINTN Index;
1329 UINT64 BufferValue;
1330
1331 if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))||
1332 (ActionRequest == NULL)) {
1333 return EFI_INVALID_PARAMETER;
1334 }
1335
1336
1337 FormId = 0;
1338 ProgressErr = 0;
1339 Status = EFI_SUCCESS;
1340 BufferValue = 3;
1341 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1342
1343 switch (Action) {
1344 case EFI_BROWSER_ACTION_FORM_OPEN:
1345 {
1346 if (QuestionId == 0x1234) {
1347 //
1348 // Sample CallBack for UEFI FORM_OPEN action:
1349 // Add Save action into Form 3 when Form 1 is opened.
1350 // This will be done only in FORM_OPEN CallBack of question with ID 0x1234 from Form 1.
1351 //
1352 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1353
1354 //
1355 // Initialize the container for dynamic opcodes
1356 //
1357 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1358 ASSERT (StartOpCodeHandle != NULL);
1359
1360 //
1361 // Create Hii Extend Label OpCode as the start opcode
1362 //
1363 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1364 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1365 StartLabel->Number = LABEL_UPDATE2;
1366
1367 HiiCreateActionOpCode (
1368 StartOpCodeHandle, // Container for dynamic created opcodes
1369 0x1238, // Question ID
1370 STRING_TOKEN(STR_SAVE_TEXT), // Prompt text
1371 STRING_TOKEN(STR_SAVE_TEXT), // Help text
1372 EFI_IFR_FLAG_CALLBACK, // Question flag
1373 0 // Action String ID
1374 );
1375
1376 HiiUpdateForm (
1377 PrivateData->HiiHandle[0], // HII handle
1378 &gDriverSampleFormSetGuid, // Formset GUID
1379 0x3, // Form ID
1380 StartOpCodeHandle, // Label for where to insert opcodes
1381 NULL // Insert data
1382 );
1383
1384 HiiFreeOpCodeHandle (StartOpCodeHandle);
1385 }
1386
1387 if (QuestionId == 0x1247) {
1388 Status = InternalStartMonitor ();
1389 ASSERT_EFI_ERROR (Status);
1390 }
1391 }
1392 break;
1393
1394 case EFI_BROWSER_ACTION_FORM_CLOSE:
1395 {
1396 if (QuestionId == 0x5678) {
1397 //
1398 // Sample CallBack for UEFI FORM_CLOSE action:
1399 // Show up a pop-up to specify Form 3 will be closed when exit Form 3.
1400 //
1401 do {
1402 CreatePopUp (
1403 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1404 &Key,
1405 L"",
1406 L"You are going to leave third Form!",
1407 L"Press ESC or ENTER to continue ...",
1408 L"",
1409 NULL
1410 );
1411 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1412 }
1413
1414 if (QuestionId == 0x1247) {
1415 Status = InternalStopMonitor ();
1416 ASSERT_EFI_ERROR (Status);
1417 }
1418 }
1419 break;
1420
1421 case EFI_BROWSER_ACTION_RETRIEVE:
1422 {
1423 switch (QuestionId ) {
1424 case 0x1248:
1425 if (Type != EFI_IFR_TYPE_REF) {
1426 return EFI_INVALID_PARAMETER;
1427 }
1428 Value->ref.FormId = 0x3;
1429 break;
1430
1431 case 0x5678:
1432 case 0x1247:
1433 //
1434 // We will reach here once the Question is refreshed
1435 //
1436
1437 //
1438 // Initialize the container for dynamic opcodes
1439 //
1440 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1441 ASSERT (StartOpCodeHandle != NULL);
1442
1443 //
1444 // Create Hii Extend Label OpCode as the start opcode
1445 //
1446 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1447 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1448 if (QuestionId == 0x5678) {
1449 StartLabel->Number = LABEL_UPDATE2;
1450 FormId = 0x03;
1451 PrivateData->Configuration.DynamicRefresh++;
1452 } else if (QuestionId == 0x1247 ) {
1453 StartLabel->Number = LABEL_UPDATE3;
1454 FormId = 0x06;
1455 PrivateData->Configuration.RefreshGuidCount++;
1456 }
1457
1458 HiiCreateActionOpCode (
1459 StartOpCodeHandle, // Container for dynamic created opcodes
1460 0x1237, // Question ID
1461 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
1462 STRING_TOKEN(STR_EXIT_TEXT), // Help text
1463 EFI_IFR_FLAG_CALLBACK, // Question flag
1464 0 // Action String ID
1465 );
1466
1467 HiiUpdateForm (
1468 PrivateData->HiiHandle[0], // HII handle
1469 &gDriverSampleFormSetGuid, // Formset GUID
1470 FormId, // Form ID
1471 StartOpCodeHandle, // Label for where to insert opcodes
1472 NULL // Insert data
1473 );
1474
1475 HiiFreeOpCodeHandle (StartOpCodeHandle);
1476
1477 //
1478 // Refresh the Question value
1479 //
1480 Status = gRT->SetVariable(
1481 VariableName,
1482 &gDriverSampleFormSetGuid,
1483 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1484 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1485 &PrivateData->Configuration
1486 );
1487
1488 if (QuestionId == 0x5678) {
1489 //
1490 // Update uncommitted data of Browser
1491 //
1492 EfiData = AllocateZeroPool (sizeof (MY_EFI_VARSTORE_DATA));
1493 ASSERT (EfiData != NULL);
1494 if (HiiGetBrowserData (&gDriverSampleFormSetGuid, MyEfiVar, sizeof (MY_EFI_VARSTORE_DATA), (UINT8 *) EfiData)) {
1495 EfiData->Field8 = 111;
1496 HiiSetBrowserData (
1497 &gDriverSampleFormSetGuid,
1498 MyEfiVar,
1499 sizeof (MY_EFI_VARSTORE_DATA),
1500 (UINT8 *) EfiData,
1501 NULL
1502 );
1503 }
1504 FreePool (EfiData);
1505 }
1506 break;
1507 }
1508 }
1509 break;
1510
1511 case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
1512 {
1513 switch (QuestionId) {
1514 case 0x1240:
1515 Value->u8 = DEFAULT_CLASS_STANDARD_VALUE;
1516 break;
1517
1518 case 0x1252:
1519 for (Index = 0; Index < 3; Index ++) {
1520 SetArrayData (Value, EFI_IFR_TYPE_NUM_SIZE_8, Index, BufferValue--);
1521 }
1522 break;
1523
1524 default:
1525 Status = EFI_UNSUPPORTED;
1526 break;
1527 }
1528 }
1529 break;
1530
1531 case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
1532 {
1533 switch (QuestionId) {
1534 case 0x1240:
1535 Value->u8 = DEFAULT_CLASS_MANUFACTURING_VALUE;
1536 break;
1537
1538 default:
1539 Status = EFI_UNSUPPORTED;
1540 break;
1541 }
1542 }
1543 break;
1544
1545 case EFI_BROWSER_ACTION_CHANGING:
1546 {
1547 switch (QuestionId) {
1548 case 0x1249:
1549 {
1550 if (Type != EFI_IFR_TYPE_REF) {
1551 return EFI_INVALID_PARAMETER;
1552 }
1553
1554 Value->ref.FormId = 0x1234;
1555 }
1556 break;
1557 case 0x1234:
1558 //
1559 // Initialize the container for dynamic opcodes
1560 //
1561 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1562 ASSERT (StartOpCodeHandle != NULL);
1563
1564 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
1565 ASSERT (EndOpCodeHandle != NULL);
1566
1567 //
1568 // Create Hii Extend Label OpCode as the start opcode
1569 //
1570 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1571 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1572 StartLabel->Number = LABEL_UPDATE1;
1573
1574 //
1575 // Create Hii Extend Label OpCode as the end opcode
1576 //
1577 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1578 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1579 EndLabel->Number = LABEL_END;
1580
1581 HiiCreateActionOpCode (
1582 StartOpCodeHandle, // Container for dynamic created opcodes
1583 0x1237, // Question ID
1584 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
1585 STRING_TOKEN(STR_EXIT_TEXT), // Help text
1586 EFI_IFR_FLAG_CALLBACK, // Question flag
1587 0 // Action String ID
1588 );
1589
1590 //
1591 // Create Option OpCode
1592 //
1593 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
1594 ASSERT (OptionsOpCodeHandle != NULL);
1595
1596 HiiCreateOneOfOptionOpCode (
1597 OptionsOpCodeHandle,
1598 STRING_TOKEN (STR_BOOT_OPTION1),
1599 0,
1600 EFI_IFR_NUMERIC_SIZE_1,
1601 1
1602 );
1603
1604 HiiCreateOneOfOptionOpCode (
1605 OptionsOpCodeHandle,
1606 STRING_TOKEN (STR_BOOT_OPTION2),
1607 0,
1608 EFI_IFR_NUMERIC_SIZE_1,
1609 2
1610 );
1611
1612 //
1613 // Prepare initial value for the dynamic created oneof Question
1614 //
1615 PrivateData->Configuration.DynamicOneof = 2;
1616 Status = gRT->SetVariable(
1617 VariableName,
1618 &gDriverSampleFormSetGuid,
1619 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1620 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1621 &PrivateData->Configuration
1622 );
1623
1624 //
1625 // Set initial vlaue of dynamic created oneof Question in Form Browser
1626 //
1627 Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
1628 ASSERT (Configuration != NULL);
1629 if (HiiGetBrowserData (&gDriverSampleFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
1630 Configuration->DynamicOneof = 2;
1631
1632 //
1633 // Update uncommitted data of Browser
1634 //
1635 HiiSetBrowserData (
1636 &gDriverSampleFormSetGuid,
1637 VariableName,
1638 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1639 (UINT8 *) Configuration,
1640 NULL
1641 );
1642 }
1643 FreePool (Configuration);
1644
1645 HiiCreateOneOfOpCode (
1646 StartOpCodeHandle, // Container for dynamic created opcodes
1647 0x8001, // Question ID (or call it "key")
1648 CONFIGURATION_VARSTORE_ID, // VarStore ID
1649 (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET, // Offset in Buffer Storage
1650 STRING_TOKEN (STR_ONE_OF_PROMPT), // Question prompt text
1651 STRING_TOKEN (STR_ONE_OF_HELP), // Question help text
1652 EFI_IFR_FLAG_CALLBACK, // Question flag
1653 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
1654 OptionsOpCodeHandle, // Option Opcode list
1655 NULL // Default Opcode is NULl
1656 );
1657
1658 HiiCreateOrderedListOpCode (
1659 StartOpCodeHandle, // Container for dynamic created opcodes
1660 0x8002, // Question ID
1661 CONFIGURATION_VARSTORE_ID, // VarStore ID
1662 (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
1663 STRING_TOKEN (STR_BOOT_OPTIONS), // Question prompt text
1664 STRING_TOKEN (STR_BOOT_OPTIONS), // Question help text
1665 EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
1666 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1667 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
1668 5, // Maximum container
1669 OptionsOpCodeHandle, // Option Opcode list
1670 NULL // Default Opcode is NULl
1671 );
1672
1673 HiiCreateTextOpCode (
1674 StartOpCodeHandle,
1675 STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
1676 STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
1677 STRING_TOKEN(STR_TEXT_SAMPLE_STRING)
1678 );
1679
1680 HiiCreateDateOpCode (
1681 StartOpCodeHandle,
1682 0x8004,
1683 0x0,
1684 0x0,
1685 STRING_TOKEN(STR_DATE_SAMPLE_HELP),
1686 STRING_TOKEN(STR_DATE_SAMPLE_HELP),
1687 0,
1688 QF_DATE_STORAGE_TIME,
1689 NULL
1690 );
1691
1692 HiiCreateTimeOpCode (
1693 StartOpCodeHandle,
1694 0x8005,
1695 0x0,
1696 0x0,
1697 STRING_TOKEN(STR_TIME_SAMPLE_HELP),
1698 STRING_TOKEN(STR_TIME_SAMPLE_HELP),
1699 0,
1700 QF_TIME_STORAGE_TIME,
1701 NULL
1702 );
1703
1704 HiiCreateGotoOpCode (
1705 StartOpCodeHandle, // Container for dynamic created opcodes
1706 1, // Target Form ID
1707 STRING_TOKEN (STR_GOTO_FORM1), // Prompt text
1708 STRING_TOKEN (STR_GOTO_HELP), // Help text
1709 0, // Question flag
1710 0x8003 // Question ID
1711 );
1712
1713 HiiUpdateForm (
1714 PrivateData->HiiHandle[0], // HII handle
1715 &gDriverSampleFormSetGuid, // Formset GUID
1716 0x1234, // Form ID
1717 StartOpCodeHandle, // Label for where to insert opcodes
1718 EndOpCodeHandle // Replace data
1719 );
1720
1721 HiiFreeOpCodeHandle (StartOpCodeHandle);
1722 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
1723 HiiFreeOpCodeHandle (EndOpCodeHandle);
1724 break;
1725
1726 case 0x2000:
1727 //
1728 // Only used to update the state.
1729 //
1730 if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0) &&
1731 (PrivateData->PasswordState == BROWSER_STATE_SET_PASSWORD)) {
1732 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1733 return EFI_INVALID_PARAMETER;
1734 }
1735
1736 //
1737 // When try to set a new password, user will be chanlleged with old password.
1738 // The Callback is responsible for validating old password input by user,
1739 // If Callback return EFI_SUCCESS, it indicates validation pass.
1740 //
1741 switch (PrivateData->PasswordState) {
1742 case BROWSER_STATE_VALIDATE_PASSWORD:
1743 Status = ValidatePassword (PrivateData, Value->string);
1744 if (Status == EFI_SUCCESS) {
1745 PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
1746 }
1747 break;
1748
1749 case BROWSER_STATE_SET_PASSWORD:
1750 Status = SetPassword (PrivateData, Value->string);
1751 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1752 break;
1753
1754 default:
1755 break;
1756 }
1757
1758 break;
1759
1760 default:
1761 break;
1762 }
1763 }
1764 break;
1765
1766 case EFI_BROWSER_ACTION_CHANGED:
1767 switch (QuestionId) {
1768 case 0x1237:
1769 //
1770 // User press "Exit now", request Browser to exit
1771 //
1772 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
1773 break;
1774
1775 case 0x1238:
1776 //
1777 // User press "Save now", request Browser to save the uncommitted data.
1778 //
1779 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1780 break;
1781
1782 case 0x1241:
1783 case 0x1246:
1784 //
1785 // User press "Submit current form and Exit now", request Browser to submit current form and exit
1786 //
1787 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
1788 break;
1789
1790 case 0x1242:
1791 //
1792 // User press "Discard current form now", request Browser to discard the uncommitted data.
1793 //
1794 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD;
1795 break;
1796
1797 case 0x1243:
1798 //
1799 // User press "Submit current form now", request Browser to save the uncommitted data.
1800 //
1801 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
1802 break;
1803
1804 case 0x1244:
1805 case 0x1245:
1806 //
1807 // User press "Discard current form and Exit now", request Browser to discard the uncommitted data and exit.
1808 //
1809 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
1810 break;
1811
1812 case 0x1231:
1813 //
1814 // 1. Check to see whether system support keyword.
1815 //
1816 Status = PrivateData->HiiKeywordHandler->GetData (PrivateData->HiiKeywordHandler,
1817 L"NAMESPACE=x-UEFI-ns",
1818 L"KEYWORD=iSCSIBootEnable",
1819 &Progress,
1820 &ProgressErr,
1821 &Results
1822 );
1823 if (EFI_ERROR (Status)) {
1824 do {
1825 CreatePopUp (
1826 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1827 &Key,
1828 L"",
1829 L"This system not support this keyword!",
1830 L"Press ENTER to continue ...",
1831 L"",
1832 NULL
1833 );
1834 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1835
1836 Status = EFI_SUCCESS;
1837 break;
1838 }
1839
1840 //
1841 // 2. If system support this keyword, just try to change value.
1842 //
1843
1844 //
1845 // Change value from '0' to '1' or from '1' to '0'
1846 //
1847 TmpStr = StrStr (Results, L"&VALUE=");
1848 ASSERT (TmpStr != NULL);
1849 TmpStr += StrLen (L"&VALUE=");
1850 TmpStr++;
1851 if (*TmpStr == L'0') {
1852 *TmpStr = L'1';
1853 } else {
1854 *TmpStr = L'0';
1855 }
1856
1857 //
1858 // 3. Call the keyword handler protocol to change the value.
1859 //
1860 Status = PrivateData->HiiKeywordHandler->SetData (PrivateData->HiiKeywordHandler,
1861 Results,
1862 &Progress,
1863 &ProgressErr
1864 );
1865 if (EFI_ERROR (Status)) {
1866 do {
1867 CreatePopUp (
1868 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1869 &Key,
1870 L"",
1871 L"Set keyword to the system failed!",
1872 L"Press ENTER to continue ...",
1873 L"",
1874 NULL
1875 );
1876 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1877
1878 Status = EFI_SUCCESS;
1879 break;
1880 }
1881 break;
1882
1883 default:
1884 break;
1885 }
1886 break;
1887
1888 case EFI_BROWSER_ACTION_SUBMITTED:
1889 {
1890 if (QuestionId == 0x1250) {
1891 //
1892 // Sample CallBack for EFI_BROWSER_ACTION_SUBMITTED action:
1893 // Show up a pop-up to show SUBMITTED callback has been triggered.
1894 //
1895 do {
1896 CreatePopUp (
1897 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1898 &Key,
1899 L"",
1900 L"EfiVarstore value has been submitted!",
1901 L"Press ESC or ENTER to continue ...",
1902 L"",
1903 NULL
1904 );
1905 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1906 }
1907 }
1908 break;
1909
1910 default:
1911 Status = EFI_UNSUPPORTED;
1912 break;
1913 }
1914
1915 return Status;
1916 }
1917
1918 /**
1919 Main entry for this driver.
1920
1921 @param ImageHandle Image handle this driver.
1922 @param SystemTable Pointer to SystemTable.
1923
1924 @retval EFI_SUCESS This function always complete successfully.
1925
1926 **/
1927 EFI_STATUS
1928 EFIAPI
1929 DriverSampleInit (
1930 IN EFI_HANDLE ImageHandle,
1931 IN EFI_SYSTEM_TABLE *SystemTable
1932 )
1933 {
1934 EFI_STATUS Status;
1935 EFI_HII_HANDLE HiiHandle[2];
1936 EFI_SCREEN_DESCRIPTOR Screen;
1937 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
1938 EFI_HII_STRING_PROTOCOL *HiiString;
1939 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
1940 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1941 EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
1942 CHAR16 *NewString;
1943 UINTN BufferSize;
1944 DRIVER_SAMPLE_CONFIGURATION *Configuration;
1945 BOOLEAN ActionFlag;
1946 EFI_STRING ConfigRequestHdr;
1947 EFI_STRING NameRequestHdr;
1948 MY_EFI_VARSTORE_DATA *VarStoreConfig;
1949 EFI_INPUT_KEY HotKey;
1950 EFI_FORM_BROWSER_EXTENSION_PROTOCOL *FormBrowserEx;
1951
1952 //
1953 // Initialize the local variables.
1954 //
1955 ConfigRequestHdr = NULL;
1956 NewString = NULL;
1957
1958 //
1959 // Initialize screen dimensions for SendForm().
1960 // Remove 3 characters from top and bottom
1961 //
1962 ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
1963 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
1964
1965 Screen.TopRow = 3;
1966 Screen.BottomRow = Screen.BottomRow - 3;
1967
1968 //
1969 // Initialize driver private data
1970 //
1971 mPrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
1972 if (mPrivateData == NULL) {
1973 return EFI_OUT_OF_RESOURCES;
1974 }
1975
1976 mPrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
1977
1978 mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
1979 mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
1980 mPrivateData->ConfigAccess.Callback = DriverCallback;
1981 mPrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1982
1983 //
1984 // Locate Hii Database protocol
1985 //
1986 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
1987 if (EFI_ERROR (Status)) {
1988 return Status;
1989 }
1990 mPrivateData->HiiDatabase = HiiDatabase;
1991
1992 //
1993 // Locate HiiString protocol
1994 //
1995 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
1996 if (EFI_ERROR (Status)) {
1997 return Status;
1998 }
1999 mPrivateData->HiiString = HiiString;
2000
2001 //
2002 // Locate Formbrowser2 protocol
2003 //
2004 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
2005 if (EFI_ERROR (Status)) {
2006 return Status;
2007 }
2008 mPrivateData->FormBrowser2 = FormBrowser2;
2009
2010 //
2011 // Locate ConfigRouting protocol
2012 //
2013 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
2014 if (EFI_ERROR (Status)) {
2015 return Status;
2016 }
2017 mPrivateData->HiiConfigRouting = HiiConfigRouting;
2018
2019 //
2020 // Locate keyword handler protocol
2021 //
2022 Status = gBS->LocateProtocol (&gEfiConfigKeywordHandlerProtocolGuid, NULL, (VOID **) &HiiKeywordHandler);
2023 if (EFI_ERROR (Status)) {
2024 return Status;
2025 }
2026 mPrivateData->HiiKeywordHandler = HiiKeywordHandler;
2027
2028 Status = gBS->InstallMultipleProtocolInterfaces (
2029 &DriverHandle[0],
2030 &gEfiDevicePathProtocolGuid,
2031 &mHiiVendorDevicePath0,
2032 &gEfiHiiConfigAccessProtocolGuid,
2033 &mPrivateData->ConfigAccess,
2034 NULL
2035 );
2036 ASSERT_EFI_ERROR (Status);
2037
2038 mPrivateData->DriverHandle[0] = DriverHandle[0];
2039
2040 //
2041 // Publish our HII data
2042 //
2043 HiiHandle[0] = HiiAddPackages (
2044 &gDriverSampleFormSetGuid,
2045 DriverHandle[0],
2046 DriverSampleStrings,
2047 VfrBin,
2048 NULL
2049 );
2050 if (HiiHandle[0] == NULL) {
2051 return EFI_OUT_OF_RESOURCES;
2052 }
2053
2054 mPrivateData->HiiHandle[0] = HiiHandle[0];
2055
2056 //
2057 // Publish another Fromset
2058 //
2059 Status = gBS->InstallMultipleProtocolInterfaces (
2060 &DriverHandle[1],
2061 &gEfiDevicePathProtocolGuid,
2062 &mHiiVendorDevicePath1,
2063 &gEfiHiiConfigAccessProtocolGuid,
2064 &mPrivateData->ConfigAccess,
2065 NULL
2066 );
2067 ASSERT_EFI_ERROR (Status);
2068
2069 mPrivateData->DriverHandle[1] = DriverHandle[1];
2070
2071 HiiHandle[1] = HiiAddPackages (
2072 &gDriverSampleInventoryGuid,
2073 DriverHandle[1],
2074 DriverSampleStrings,
2075 InventoryBin,
2076 NULL
2077 );
2078 if (HiiHandle[1] == NULL) {
2079 DriverSampleUnload (ImageHandle);
2080 return EFI_OUT_OF_RESOURCES;
2081 }
2082
2083 mPrivateData->HiiHandle[1] = HiiHandle[1];
2084
2085 //
2086 // Update the device path string.
2087 //
2088 NewString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)&mHiiVendorDevicePath0, FALSE, FALSE);
2089 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_DEVICE_PATH), NewString, NULL) == 0) {
2090 DriverSampleUnload (ImageHandle);
2091 return EFI_OUT_OF_RESOURCES;
2092 }
2093 if (NewString != NULL) {
2094 FreePool (NewString);
2095 }
2096
2097 //
2098 // Very simple example of how one would update a string that is already
2099 // in the HII database
2100 //
2101 NewString = L"700 Mhz";
2102
2103 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
2104 DriverSampleUnload (ImageHandle);
2105 return EFI_OUT_OF_RESOURCES;
2106 }
2107
2108 HiiSetString (HiiHandle[0], 0, NewString, NULL);
2109
2110 //
2111 // Initialize Name/Value name String ID
2112 //
2113 mPrivateData->NameStringId[0] = STR_NAME_VALUE_VAR_NAME0;
2114 mPrivateData->NameStringId[1] = STR_NAME_VALUE_VAR_NAME1;
2115 mPrivateData->NameStringId[2] = STR_NAME_VALUE_VAR_NAME2;
2116
2117 //
2118 // Initialize configuration data
2119 //
2120 Configuration = &mPrivateData->Configuration;
2121 ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
2122
2123 //
2124 // Try to read NV config EFI variable first
2125 //
2126 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, DriverHandle[0]);
2127 ASSERT (ConfigRequestHdr != NULL);
2128
2129 NameRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, NULL, DriverHandle[0]);
2130 ASSERT (NameRequestHdr != NULL);
2131
2132 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
2133 Status = gRT->GetVariable (VariableName, &gDriverSampleFormSetGuid, NULL, &BufferSize, Configuration);
2134 if (EFI_ERROR (Status)) {
2135 //
2136 // Store zero data Buffer Storage to EFI variable
2137 //
2138 Status = gRT->SetVariable(
2139 VariableName,
2140 &gDriverSampleFormSetGuid,
2141 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
2142 sizeof (DRIVER_SAMPLE_CONFIGURATION),
2143 Configuration
2144 );
2145 if (EFI_ERROR (Status)) {
2146 DriverSampleUnload (ImageHandle);
2147 return Status;
2148 }
2149 //
2150 // EFI variable for NV config doesn't exit, we should build this variable
2151 // based on default values stored in IFR
2152 //
2153 ActionFlag = HiiSetToDefaults (NameRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2154 if (!ActionFlag) {
2155 DriverSampleUnload (ImageHandle);
2156 return EFI_INVALID_PARAMETER;
2157 }
2158
2159 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2160 if (!ActionFlag) {
2161 DriverSampleUnload (ImageHandle);
2162 return EFI_INVALID_PARAMETER;
2163 }
2164 } else {
2165 //
2166 // EFI variable does exist and Validate Current Setting
2167 //
2168 ActionFlag = HiiValidateSettings (NameRequestHdr);
2169 if (!ActionFlag) {
2170 DriverSampleUnload (ImageHandle);
2171 return EFI_INVALID_PARAMETER;
2172 }
2173
2174 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
2175 if (!ActionFlag) {
2176 DriverSampleUnload (ImageHandle);
2177 return EFI_INVALID_PARAMETER;
2178 }
2179 }
2180 FreePool (ConfigRequestHdr);
2181
2182 //
2183 // Initialize efi varstore configuration data
2184 //
2185 VarStoreConfig = &mPrivateData->VarStoreConfig;
2186 ZeroMem (VarStoreConfig, sizeof (MY_EFI_VARSTORE_DATA));
2187
2188 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, MyEfiVar, DriverHandle[0]);
2189 ASSERT (ConfigRequestHdr != NULL);
2190
2191 BufferSize = sizeof (MY_EFI_VARSTORE_DATA);
2192 Status = gRT->GetVariable (MyEfiVar, &gDriverSampleFormSetGuid, NULL, &BufferSize, VarStoreConfig);
2193 if (EFI_ERROR (Status)) {
2194 //
2195 // Store zero data to EFI variable Storage.
2196 //
2197 Status = gRT->SetVariable(
2198 MyEfiVar,
2199 &gDriverSampleFormSetGuid,
2200 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
2201 sizeof (MY_EFI_VARSTORE_DATA),
2202 VarStoreConfig
2203 );
2204 if (EFI_ERROR (Status)) {
2205 DriverSampleUnload (ImageHandle);
2206 return Status;
2207 }
2208 //
2209 // EFI variable for NV config doesn't exit, we should build this variable
2210 // based on default values stored in IFR
2211 //
2212 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2213 if (!ActionFlag) {
2214 DriverSampleUnload (ImageHandle);
2215 return EFI_INVALID_PARAMETER;
2216 }
2217 } else {
2218 //
2219 // EFI variable does exist and Validate Current Setting
2220 //
2221 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
2222 if (!ActionFlag) {
2223 DriverSampleUnload (ImageHandle);
2224 return EFI_INVALID_PARAMETER;
2225 }
2226 }
2227 FreePool (ConfigRequestHdr);
2228
2229 Status = gBS->CreateEventEx (
2230 EVT_NOTIFY_SIGNAL,
2231 TPL_NOTIFY,
2232 DriverSampleInternalEmptyFunction,
2233 NULL,
2234 &gEfiIfrRefreshIdOpGuid,
2235 &mEvent
2236 );
2237 ASSERT_EFI_ERROR (Status);
2238
2239 //
2240 // Example of how to use BrowserEx protocol to register HotKey.
2241 //
2242 Status = gBS->LocateProtocol (&gEfiFormBrowserExProtocolGuid, NULL, (VOID **) &FormBrowserEx);
2243 if (!EFI_ERROR (Status)) {
2244 //
2245 // First unregister the default hot key F9 and F10.
2246 //
2247 HotKey.UnicodeChar = CHAR_NULL;
2248 HotKey.ScanCode = SCAN_F9;
2249 FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
2250 HotKey.ScanCode = SCAN_F10;
2251 FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
2252
2253 //
2254 // Register the default HotKey F9 and F10 again.
2255 //
2256 HotKey.ScanCode = SCAN_F10;
2257 NewString = HiiGetString (mPrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
2258 ASSERT (NewString != NULL);
2259 FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
2260 HotKey.ScanCode = SCAN_F9;
2261 NewString = HiiGetString (mPrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
2262 ASSERT (NewString != NULL);
2263 FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
2264 }
2265
2266 //
2267 // In default, this driver is built into Flash device image,
2268 // the following code doesn't run.
2269 //
2270
2271 //
2272 // Example of how to display only the item we sent to HII
2273 // When this driver is not built into Flash device image,
2274 // it need to call SendForm to show front page by itself.
2275 //
2276 if (DISPLAY_ONLY_MY_ITEM <= 1) {
2277 //
2278 // Have the browser pull out our copy of the data, and only display our data
2279 //
2280 Status = FormBrowser2->SendForm (
2281 FormBrowser2,
2282 &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
2283 1,
2284 NULL,
2285 0,
2286 NULL,
2287 NULL
2288 );
2289
2290 HiiRemovePackages (HiiHandle[0]);
2291
2292 HiiRemovePackages (HiiHandle[1]);
2293 }
2294
2295 return EFI_SUCCESS;
2296 }
2297
2298 /**
2299 Unloads the application and its installed protocol.
2300
2301 @param[in] ImageHandle Handle that identifies the image to be unloaded.
2302
2303 @retval EFI_SUCCESS The image has been unloaded.
2304 **/
2305 EFI_STATUS
2306 EFIAPI
2307 DriverSampleUnload (
2308 IN EFI_HANDLE ImageHandle
2309 )
2310 {
2311 UINTN Index;
2312
2313 ASSERT (mPrivateData != NULL);
2314
2315 if (DriverHandle[0] != NULL) {
2316 gBS->UninstallMultipleProtocolInterfaces (
2317 DriverHandle[0],
2318 &gEfiDevicePathProtocolGuid,
2319 &mHiiVendorDevicePath0,
2320 &gEfiHiiConfigAccessProtocolGuid,
2321 &mPrivateData->ConfigAccess,
2322 NULL
2323 );
2324 DriverHandle[0] = NULL;
2325 }
2326
2327 if (DriverHandle[1] != NULL) {
2328 gBS->UninstallMultipleProtocolInterfaces (
2329 DriverHandle[1],
2330 &gEfiDevicePathProtocolGuid,
2331 &mHiiVendorDevicePath1,
2332 &gEfiHiiConfigAccessProtocolGuid,
2333 &mPrivateData->ConfigAccess,
2334 NULL
2335 );
2336 DriverHandle[1] = NULL;
2337 }
2338
2339 if (mPrivateData->HiiHandle[0] != NULL) {
2340 HiiRemovePackages (mPrivateData->HiiHandle[0]);
2341 }
2342
2343 if (mPrivateData->HiiHandle[1] != NULL) {
2344 HiiRemovePackages (mPrivateData->HiiHandle[1]);
2345 }
2346
2347 for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {
2348 if (mPrivateData->NameValueName[Index] != NULL) {
2349 FreePool (mPrivateData->NameValueName[Index]);
2350 }
2351 }
2352 FreePool (mPrivateData);
2353 mPrivateData = NULL;
2354
2355 gBS->CloseEvent (mEvent);
2356
2357 return EFI_SUCCESS;
2358 }