]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
MdeModulePkg/Universal: Fix typos in comments
[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 // Retrieve 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 // Skip the character "&" before "OFFSET".
782 //
783 StringPtr ++;
784
785 //
786 // Calculate Value and convert it to hex string.
787 //
788 if (Offset + Width > BlockSize) {
789 return;
790 }
791
792 if (Offset <= ValueOffset && Offset + Width >= ValueOffset + ValueWidth) {
793 *RequestResult = CreateAltCfgString(*RequestResult, ConfigRequestHdr, ValueOffset, ValueWidth);
794 return;
795 }
796 }
797 }
798
799 /**
800 This function allows a caller to extract the current configuration for one
801 or more named elements from the target driver.
802
803 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
804 @param Request A null-terminated Unicode string in
805 <ConfigRequest> format.
806 @param Progress On return, points to a character in the Request
807 string. Points to the string's null terminator if
808 request was successful. Points to the most recent
809 '&' before the first failing name/value pair (or
810 the beginning of the string if the failure is in
811 the first name/value pair) if the request was not
812 successful.
813 @param Results A null-terminated Unicode string in
814 <ConfigAltResp> format which has all values filled
815 in for the names in the Request string. String to
816 be allocated by the called function.
817
818 @retval EFI_SUCCESS The Results is filled with the requested values.
819 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
820 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
821 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
822 driver.
823
824 **/
825 EFI_STATUS
826 EFIAPI
827 ExtractConfig (
828 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
829 IN CONST EFI_STRING Request,
830 OUT EFI_STRING *Progress,
831 OUT EFI_STRING *Results
832 )
833 {
834 EFI_STATUS Status;
835 UINTN BufferSize;
836 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
837 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
838 EFI_STRING ConfigRequest;
839 EFI_STRING ConfigRequestHdr;
840 UINTN Size;
841 EFI_STRING Value;
842 UINTN ValueStrLen;
843 CHAR16 BackupChar;
844 CHAR16 *StrPointer;
845 BOOLEAN AllocatedRequest;
846
847 if (Progress == NULL || Results == NULL) {
848 return EFI_INVALID_PARAMETER;
849 }
850 //
851 // Initialize the local variables.
852 //
853 ConfigRequestHdr = NULL;
854 ConfigRequest = NULL;
855 Size = 0;
856 *Progress = Request;
857 AllocatedRequest = FALSE;
858
859 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
860 HiiConfigRouting = PrivateData->HiiConfigRouting;
861
862 //
863 // Get Buffer Storage data from EFI variable.
864 // Try to get the current setting from variable.
865 //
866 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
867 Status = gRT->GetVariable (
868 VariableName,
869 &gDriverSampleFormSetGuid,
870 NULL,
871 &BufferSize,
872 &PrivateData->Configuration
873 );
874 if (EFI_ERROR (Status)) {
875 return EFI_NOT_FOUND;
876 }
877
878 if (Request == NULL) {
879 //
880 // Request is set to NULL, construct full request string.
881 //
882
883 //
884 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
885 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
886 //
887 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, PrivateData->DriverHandle[0]);
888 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
889 ConfigRequest = AllocateZeroPool (Size);
890 ASSERT (ConfigRequest != NULL);
891 AllocatedRequest = TRUE;
892 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
893 FreePool (ConfigRequestHdr);
894 ConfigRequestHdr = NULL;
895 } else {
896 //
897 // Check routing data in <ConfigHdr>.
898 // Note: if only one Storage is used, then this checking could be skipped.
899 //
900 if (!HiiIsConfigHdrMatch (Request, &gDriverSampleFormSetGuid, NULL)) {
901 return EFI_NOT_FOUND;
902 }
903 //
904 // Check whether request for EFI Varstore. EFI varstore get data
905 // through hii database, not support in this path.
906 //
907 if (HiiIsConfigHdrMatch(Request, &gDriverSampleFormSetGuid, MyEfiVar)) {
908 return EFI_UNSUPPORTED;
909 }
910 //
911 // Set Request to the unified request string.
912 //
913 ConfigRequest = Request;
914 //
915 // Check whether Request includes Request Element.
916 //
917 if (StrStr (Request, L"OFFSET") == NULL) {
918 //
919 // Check Request Element does exist in Reques String
920 //
921 StrPointer = StrStr (Request, L"PATH");
922 if (StrPointer == NULL) {
923 return EFI_INVALID_PARAMETER;
924 }
925 if (StrStr (StrPointer, L"&") == NULL) {
926 Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);
927 ConfigRequest = AllocateZeroPool (Size);
928 ASSERT (ConfigRequest != NULL);
929 AllocatedRequest = TRUE;
930 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", Request, (UINT64)BufferSize);
931 }
932 }
933 }
934
935 //
936 // Check if requesting Name/Value storage
937 //
938 if (StrStr (ConfigRequest, L"OFFSET") == NULL) {
939 //
940 // Update Name/Value storage Names
941 //
942 Status = LoadNameValueNames (PrivateData);
943 if (EFI_ERROR (Status)) {
944 return Status;
945 }
946
947 //
948 // Allocate memory for <ConfigResp>, e.g. Name0=0x11, Name1=0x1234, Name2="ABCD"
949 // <Request> ::=<ConfigHdr>&Name0&Name1&Name2
950 // <ConfigResp>::=<ConfigHdr>&Name0=11&Name1=1234&Name2=0041004200430044
951 //
952 BufferSize = (StrLen (ConfigRequest) +
953 1 + sizeof (PrivateData->Configuration.NameValueVar0) * 2 +
954 1 + sizeof (PrivateData->Configuration.NameValueVar1) * 2 +
955 1 + sizeof (PrivateData->Configuration.NameValueVar2) * 2 + 1) * sizeof (CHAR16);
956 *Results = AllocateZeroPool (BufferSize);
957 ASSERT (*Results != NULL);
958 StrCpyS (*Results, BufferSize / sizeof (CHAR16), ConfigRequest);
959 Value = *Results;
960
961 //
962 // Append value of NameValueVar0, type is UINT8
963 //
964 if ((Value = StrStr (*Results, PrivateData->NameValueName[0])) != NULL) {
965 Value += StrLen (PrivateData->NameValueName[0]);
966 ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar0) * 2) + 1);
967 CopyMem (Value + ValueStrLen, Value, StrSize (Value));
968
969 BackupChar = Value[ValueStrLen];
970 *Value++ = L'=';
971 Value += UnicodeValueToString (
972 Value,
973 PREFIX_ZERO | RADIX_HEX,
974 PrivateData->Configuration.NameValueVar0,
975 sizeof (PrivateData->Configuration.NameValueVar0) * 2
976 );
977 *Value = BackupChar;
978 }
979
980 //
981 // Append value of NameValueVar1, type is UINT16
982 //
983 if ((Value = StrStr (*Results, PrivateData->NameValueName[1])) != NULL) {
984 Value += StrLen (PrivateData->NameValueName[1]);
985 ValueStrLen = ((sizeof (PrivateData->Configuration.NameValueVar1) * 2) + 1);
986 CopyMem (Value + ValueStrLen, Value, StrSize (Value));
987
988 BackupChar = Value[ValueStrLen];
989 *Value++ = L'=';
990 Value += UnicodeValueToString (
991 Value,
992 PREFIX_ZERO | RADIX_HEX,
993 PrivateData->Configuration.NameValueVar1,
994 sizeof (PrivateData->Configuration.NameValueVar1) * 2
995 );
996 *Value = BackupChar;
997 }
998
999 //
1000 // Append value of NameValueVar2, type is CHAR16 *
1001 //
1002 if ((Value = StrStr (*Results, PrivateData->NameValueName[2])) != NULL) {
1003 Value += StrLen (PrivateData->NameValueName[2]);
1004 ValueStrLen = StrLen (PrivateData->Configuration.NameValueVar2) * 4 + 1;
1005 CopyMem (Value + ValueStrLen, Value, StrSize (Value));
1006
1007 *Value++ = L'=';
1008 //
1009 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1010 //
1011 StrPointer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;
1012 for (; *StrPointer != L'\0'; StrPointer++) {
1013 Value += UnicodeValueToString (Value, PREFIX_ZERO | RADIX_HEX, *StrPointer, 4);
1014 }
1015 }
1016
1017 Status = EFI_SUCCESS;
1018 } else {
1019 //
1020 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1021 //
1022 Status = HiiConfigRouting->BlockToConfig (
1023 HiiConfigRouting,
1024 ConfigRequest,
1025 (UINT8 *) &PrivateData->Configuration,
1026 BufferSize,
1027 Results,
1028 Progress
1029 );
1030 if (!EFI_ERROR (Status)) {
1031 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, PrivateData->DriverHandle[0]);
1032 AppendAltCfgString(Results, ConfigRequestHdr);
1033 }
1034 }
1035
1036 //
1037 // Free the allocated config request string.
1038 //
1039 if (AllocatedRequest) {
1040 FreePool (ConfigRequest);
1041 }
1042
1043 if (ConfigRequestHdr != NULL) {
1044 FreePool (ConfigRequestHdr);
1045 }
1046 //
1047 // Set Progress string to the original request string.
1048 //
1049 if (Request == NULL) {
1050 *Progress = NULL;
1051 } else if (StrStr (Request, L"OFFSET") == NULL) {
1052 *Progress = Request + StrLen (Request);
1053 }
1054
1055 return Status;
1056 }
1057
1058
1059 /**
1060 This function processes the results of changes in configuration.
1061
1062 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1063 @param Configuration A null-terminated Unicode string in <ConfigResp>
1064 format.
1065 @param Progress A pointer to a string filled in with the offset of
1066 the most recent '&' before the first failing
1067 name/value pair (or the beginning of the string if
1068 the failure is in the first name/value pair) or
1069 the terminating NULL if all was successful.
1070
1071 @retval EFI_SUCCESS The Results is processed successfully.
1072 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1073 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
1074 driver.
1075
1076 **/
1077 EFI_STATUS
1078 EFIAPI
1079 RouteConfig (
1080 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1081 IN CONST EFI_STRING Configuration,
1082 OUT EFI_STRING *Progress
1083 )
1084 {
1085 EFI_STATUS Status;
1086 UINTN BufferSize;
1087 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
1088 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1089 CHAR16 *Value;
1090 CHAR16 *StrPtr;
1091 CHAR16 TemStr[5];
1092 UINT8 *DataBuffer;
1093 UINT8 DigitUint8;
1094 UINTN Index;
1095 CHAR16 *StrBuffer;
1096
1097 if (Configuration == NULL || Progress == NULL) {
1098 return EFI_INVALID_PARAMETER;
1099 }
1100
1101 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1102 HiiConfigRouting = PrivateData->HiiConfigRouting;
1103 *Progress = Configuration;
1104
1105 //
1106 // Check routing data in <ConfigHdr>.
1107 // Note: if only one Storage is used, then this checking could be skipped.
1108 //
1109 if (!HiiIsConfigHdrMatch (Configuration, &gDriverSampleFormSetGuid, NULL)) {
1110 return EFI_NOT_FOUND;
1111 }
1112
1113 //
1114 // Check whether request for EFI Varstore. EFI varstore get data
1115 // through hii database, not support in this path.
1116 //
1117 if (HiiIsConfigHdrMatch(Configuration, &gDriverSampleFormSetGuid, MyEfiVar)) {
1118 return EFI_UNSUPPORTED;
1119 }
1120
1121 //
1122 // Get Buffer Storage data from EFI variable
1123 //
1124 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1125 Status = gRT->GetVariable (
1126 VariableName,
1127 &gDriverSampleFormSetGuid,
1128 NULL,
1129 &BufferSize,
1130 &PrivateData->Configuration
1131 );
1132 if (EFI_ERROR (Status)) {
1133 return Status;
1134 }
1135
1136 //
1137 // Check if configuring Name/Value storage
1138 //
1139 if (StrStr (Configuration, L"OFFSET") == NULL) {
1140 //
1141 // Update Name/Value storage Names
1142 //
1143 Status = LoadNameValueNames (PrivateData);
1144 if (EFI_ERROR (Status)) {
1145 return Status;
1146 }
1147
1148 //
1149 // Convert value for NameValueVar0
1150 //
1151 if ((Value = StrStr (Configuration, PrivateData->NameValueName[0])) != NULL) {
1152 //
1153 // Skip "Name="
1154 //
1155 Value += StrLen (PrivateData->NameValueName[0]);
1156 Value++;
1157 //
1158 // Get Value String
1159 //
1160 StrPtr = StrStr (Value, L"&");
1161 if (StrPtr == NULL) {
1162 StrPtr = Value + StrLen (Value);
1163 }
1164 //
1165 // Convert Value to Buffer data
1166 //
1167 DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar0;
1168 ZeroMem (TemStr, sizeof (TemStr));
1169 for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {
1170 TemStr[0] = *StrPtr;
1171 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
1172 if ((Index & 1) == 0) {
1173 DataBuffer [Index/2] = DigitUint8;
1174 } else {
1175 DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);
1176 }
1177 }
1178 }
1179
1180 //
1181 // Convert value for NameValueVar1
1182 //
1183 if ((Value = StrStr (Configuration, PrivateData->NameValueName[1])) != NULL) {
1184 //
1185 // Skip "Name="
1186 //
1187 Value += StrLen (PrivateData->NameValueName[1]);
1188 Value++;
1189 //
1190 // Get Value String
1191 //
1192 StrPtr = StrStr (Value, L"&");
1193 if (StrPtr == NULL) {
1194 StrPtr = Value + StrLen (Value);
1195 }
1196 //
1197 // Convert Value to Buffer data
1198 //
1199 DataBuffer = (UINT8 *) &PrivateData->Configuration.NameValueVar1;
1200 ZeroMem (TemStr, sizeof (TemStr));
1201 for (Index = 0, StrPtr --; StrPtr >= Value; StrPtr --, Index ++) {
1202 TemStr[0] = *StrPtr;
1203 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
1204 if ((Index & 1) == 0) {
1205 DataBuffer [Index/2] = DigitUint8;
1206 } else {
1207 DataBuffer [Index/2] = (UINT8) ((UINT8) (DigitUint8 << 4) + DataBuffer [Index/2]);
1208 }
1209 }
1210 }
1211
1212 //
1213 // Convert value for NameValueVar2
1214 //
1215 if ((Value = StrStr (Configuration, PrivateData->NameValueName[2])) != NULL) {
1216 //
1217 // Skip "Name="
1218 //
1219 Value += StrLen (PrivateData->NameValueName[2]);
1220 Value++;
1221 //
1222 // Get Value String
1223 //
1224 StrPtr = StrStr (Value, L"&");
1225 if (StrPtr == NULL) {
1226 StrPtr = Value + StrLen (Value);
1227 }
1228 //
1229 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1230 //
1231 StrBuffer = (CHAR16 *) PrivateData->Configuration.NameValueVar2;
1232 ZeroMem (TemStr, sizeof (TemStr));
1233 while (Value < StrPtr) {
1234 StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value, 4);
1235 *(StrBuffer++) = (CHAR16) StrHexToUint64 (TemStr);
1236 Value += 4;
1237 }
1238 *StrBuffer = L'\0';
1239 }
1240
1241 //
1242 // Store Buffer Storage back to EFI variable
1243 //
1244 Status = gRT->SetVariable(
1245 VariableName,
1246 &gDriverSampleFormSetGuid,
1247 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1248 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1249 &PrivateData->Configuration
1250 );
1251
1252 return Status;
1253 }
1254
1255 //
1256 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
1257 //
1258 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
1259 Status = HiiConfigRouting->ConfigToBlock (
1260 HiiConfigRouting,
1261 Configuration,
1262 (UINT8 *) &PrivateData->Configuration,
1263 &BufferSize,
1264 Progress
1265 );
1266 if (EFI_ERROR (Status)) {
1267 return Status;
1268 }
1269
1270 //
1271 // Store Buffer Storage back to EFI variable
1272 //
1273 Status = gRT->SetVariable(
1274 VariableName,
1275 &gDriverSampleFormSetGuid,
1276 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1277 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1278 &PrivateData->Configuration
1279 );
1280
1281 return Status;
1282 }
1283
1284
1285 /**
1286 This function processes the results of changes in configuration.
1287
1288 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1289 @param Action Specifies the type of action taken by the browser.
1290 @param QuestionId A unique value which is sent to the original
1291 exporting driver so that it can identify the type
1292 of data to expect.
1293 @param Type The type of value for the question.
1294 @param Value A pointer to the data being sent to the original
1295 exporting driver.
1296 @param ActionRequest On return, points to the action requested by the
1297 callback function.
1298
1299 @retval EFI_SUCCESS The callback successfully handled the action.
1300 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1301 variable and its data.
1302 @retval EFI_DEVICE_ERROR The variable could not be saved.
1303 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1304 callback.
1305
1306 **/
1307 EFI_STATUS
1308 EFIAPI
1309 DriverCallback (
1310 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1311 IN EFI_BROWSER_ACTION Action,
1312 IN EFI_QUESTION_ID QuestionId,
1313 IN UINT8 Type,
1314 IN EFI_IFR_TYPE_VALUE *Value,
1315 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1316 )
1317 {
1318 DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
1319 EFI_STATUS Status;
1320 VOID *StartOpCodeHandle;
1321 VOID *OptionsOpCodeHandle;
1322 EFI_IFR_GUID_LABEL *StartLabel;
1323 VOID *EndOpCodeHandle;
1324 EFI_IFR_GUID_LABEL *EndLabel;
1325 EFI_INPUT_KEY Key;
1326 DRIVER_SAMPLE_CONFIGURATION *Configuration;
1327 MY_EFI_VARSTORE_DATA *EfiData;
1328 EFI_FORM_ID FormId;
1329 EFI_STRING Progress;
1330 EFI_STRING Results;
1331 UINT32 ProgressErr;
1332 CHAR16 *TmpStr;
1333 UINTN Index;
1334 UINT64 BufferValue;
1335
1336 if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))||
1337 (ActionRequest == NULL)) {
1338 return EFI_INVALID_PARAMETER;
1339 }
1340
1341
1342 FormId = 0;
1343 ProgressErr = 0;
1344 Status = EFI_SUCCESS;
1345 BufferValue = 3;
1346 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1347
1348 switch (Action) {
1349 case EFI_BROWSER_ACTION_FORM_OPEN:
1350 {
1351 if (QuestionId == 0x1234) {
1352 //
1353 // Sample CallBack for UEFI FORM_OPEN action:
1354 // Add Save action into Form 3 when Form 1 is opened.
1355 // This will be done only in FORM_OPEN CallBack of question with ID 0x1234 from Form 1.
1356 //
1357 PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
1358
1359 //
1360 // Initialize the container for dynamic opcodes
1361 //
1362 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1363 ASSERT (StartOpCodeHandle != NULL);
1364
1365 //
1366 // Create Hii Extend Label OpCode as the start opcode
1367 //
1368 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1369 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1370 StartLabel->Number = LABEL_UPDATE2;
1371
1372 HiiCreateActionOpCode (
1373 StartOpCodeHandle, // Container for dynamic created opcodes
1374 0x1238, // Question ID
1375 STRING_TOKEN(STR_SAVE_TEXT), // Prompt text
1376 STRING_TOKEN(STR_SAVE_TEXT), // Help text
1377 EFI_IFR_FLAG_CALLBACK, // Question flag
1378 0 // Action String ID
1379 );
1380
1381 HiiUpdateForm (
1382 PrivateData->HiiHandle[0], // HII handle
1383 &gDriverSampleFormSetGuid, // Formset GUID
1384 0x3, // Form ID
1385 StartOpCodeHandle, // Label for where to insert opcodes
1386 NULL // Insert data
1387 );
1388
1389 HiiFreeOpCodeHandle (StartOpCodeHandle);
1390 }
1391
1392 if (QuestionId == 0x1247) {
1393 Status = InternalStartMonitor ();
1394 ASSERT_EFI_ERROR (Status);
1395 }
1396 }
1397 break;
1398
1399 case EFI_BROWSER_ACTION_FORM_CLOSE:
1400 {
1401 if (QuestionId == 0x5678) {
1402 //
1403 // Sample CallBack for UEFI FORM_CLOSE action:
1404 // Show up a pop-up to specify Form 3 will be closed when exit Form 3.
1405 //
1406 do {
1407 CreatePopUp (
1408 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1409 &Key,
1410 L"",
1411 L"You are going to leave third Form!",
1412 L"Press ESC or ENTER to continue ...",
1413 L"",
1414 NULL
1415 );
1416 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1417 }
1418
1419 if (QuestionId == 0x1247) {
1420 Status = InternalStopMonitor ();
1421 ASSERT_EFI_ERROR (Status);
1422 }
1423 }
1424 break;
1425
1426 case EFI_BROWSER_ACTION_RETRIEVE:
1427 {
1428 switch (QuestionId ) {
1429 case 0x1248:
1430 if (Type != EFI_IFR_TYPE_REF) {
1431 return EFI_INVALID_PARAMETER;
1432 }
1433 Value->ref.FormId = 0x3;
1434 break;
1435
1436 case 0x5678:
1437 case 0x1247:
1438 //
1439 // We will reach here once the Question is refreshed
1440 //
1441
1442 //
1443 // Initialize the container for dynamic opcodes
1444 //
1445 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1446 ASSERT (StartOpCodeHandle != NULL);
1447
1448 //
1449 // Create Hii Extend Label OpCode as the start opcode
1450 //
1451 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1452 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1453 if (QuestionId == 0x5678) {
1454 StartLabel->Number = LABEL_UPDATE2;
1455 FormId = 0x03;
1456 PrivateData->Configuration.DynamicRefresh++;
1457 } else if (QuestionId == 0x1247 ) {
1458 StartLabel->Number = LABEL_UPDATE3;
1459 FormId = 0x06;
1460 PrivateData->Configuration.RefreshGuidCount++;
1461 }
1462
1463 HiiCreateActionOpCode (
1464 StartOpCodeHandle, // Container for dynamic created opcodes
1465 0x1237, // Question ID
1466 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
1467 STRING_TOKEN(STR_EXIT_TEXT), // Help text
1468 EFI_IFR_FLAG_CALLBACK, // Question flag
1469 0 // Action String ID
1470 );
1471
1472 HiiUpdateForm (
1473 PrivateData->HiiHandle[0], // HII handle
1474 &gDriverSampleFormSetGuid, // Formset GUID
1475 FormId, // Form ID
1476 StartOpCodeHandle, // Label for where to insert opcodes
1477 NULL // Insert data
1478 );
1479
1480 HiiFreeOpCodeHandle (StartOpCodeHandle);
1481
1482 //
1483 // Refresh the Question value
1484 //
1485 Status = gRT->SetVariable(
1486 VariableName,
1487 &gDriverSampleFormSetGuid,
1488 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1489 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1490 &PrivateData->Configuration
1491 );
1492
1493 if (QuestionId == 0x5678) {
1494 //
1495 // Update uncommitted data of Browser
1496 //
1497 EfiData = AllocateZeroPool (sizeof (MY_EFI_VARSTORE_DATA));
1498 ASSERT (EfiData != NULL);
1499 if (HiiGetBrowserData (&gDriverSampleFormSetGuid, MyEfiVar, sizeof (MY_EFI_VARSTORE_DATA), (UINT8 *) EfiData)) {
1500 EfiData->Field8 = 111;
1501 HiiSetBrowserData (
1502 &gDriverSampleFormSetGuid,
1503 MyEfiVar,
1504 sizeof (MY_EFI_VARSTORE_DATA),
1505 (UINT8 *) EfiData,
1506 NULL
1507 );
1508 }
1509 FreePool (EfiData);
1510 }
1511 break;
1512 }
1513 }
1514 break;
1515
1516 case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
1517 {
1518 switch (QuestionId) {
1519 case 0x1240:
1520 Value->u8 = DEFAULT_CLASS_STANDARD_VALUE;
1521 break;
1522
1523 case 0x1252:
1524 for (Index = 0; Index < 3; Index ++) {
1525 SetArrayData (Value, EFI_IFR_TYPE_NUM_SIZE_8, Index, BufferValue--);
1526 }
1527 break;
1528
1529 default:
1530 Status = EFI_UNSUPPORTED;
1531 break;
1532 }
1533 }
1534 break;
1535
1536 case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
1537 {
1538 switch (QuestionId) {
1539 case 0x1240:
1540 Value->u8 = DEFAULT_CLASS_MANUFACTURING_VALUE;
1541 break;
1542
1543 default:
1544 Status = EFI_UNSUPPORTED;
1545 break;
1546 }
1547 }
1548 break;
1549
1550 case EFI_BROWSER_ACTION_CHANGING:
1551 {
1552 switch (QuestionId) {
1553 case 0x1249:
1554 {
1555 if (Type != EFI_IFR_TYPE_REF) {
1556 return EFI_INVALID_PARAMETER;
1557 }
1558
1559 Value->ref.FormId = 0x1234;
1560 }
1561 break;
1562 case 0x1234:
1563 //
1564 // Initialize the container for dynamic opcodes
1565 //
1566 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1567 ASSERT (StartOpCodeHandle != NULL);
1568
1569 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
1570 ASSERT (EndOpCodeHandle != NULL);
1571
1572 //
1573 // Create Hii Extend Label OpCode as the start opcode
1574 //
1575 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1576 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1577 StartLabel->Number = LABEL_UPDATE1;
1578
1579 //
1580 // Create Hii Extend Label OpCode as the end opcode
1581 //
1582 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1583 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1584 EndLabel->Number = LABEL_END;
1585
1586 HiiCreateActionOpCode (
1587 StartOpCodeHandle, // Container for dynamic created opcodes
1588 0x1237, // Question ID
1589 STRING_TOKEN(STR_EXIT_TEXT), // Prompt text
1590 STRING_TOKEN(STR_EXIT_TEXT), // Help text
1591 EFI_IFR_FLAG_CALLBACK, // Question flag
1592 0 // Action String ID
1593 );
1594
1595 //
1596 // Create Option OpCode
1597 //
1598 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
1599 ASSERT (OptionsOpCodeHandle != NULL);
1600
1601 HiiCreateOneOfOptionOpCode (
1602 OptionsOpCodeHandle,
1603 STRING_TOKEN (STR_BOOT_OPTION1),
1604 0,
1605 EFI_IFR_NUMERIC_SIZE_1,
1606 1
1607 );
1608
1609 HiiCreateOneOfOptionOpCode (
1610 OptionsOpCodeHandle,
1611 STRING_TOKEN (STR_BOOT_OPTION2),
1612 0,
1613 EFI_IFR_NUMERIC_SIZE_1,
1614 2
1615 );
1616
1617 //
1618 // Prepare initial value for the dynamic created oneof Question
1619 //
1620 PrivateData->Configuration.DynamicOneof = 2;
1621 Status = gRT->SetVariable(
1622 VariableName,
1623 &gDriverSampleFormSetGuid,
1624 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1625 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1626 &PrivateData->Configuration
1627 );
1628
1629 //
1630 // Set initial vlaue of dynamic created oneof Question in Form Browser
1631 //
1632 Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_CONFIGURATION));
1633 ASSERT (Configuration != NULL);
1634 if (HiiGetBrowserData (&gDriverSampleFormSetGuid, VariableName, sizeof (DRIVER_SAMPLE_CONFIGURATION), (UINT8 *) Configuration)) {
1635 Configuration->DynamicOneof = 2;
1636
1637 //
1638 // Update uncommitted data of Browser
1639 //
1640 HiiSetBrowserData (
1641 &gDriverSampleFormSetGuid,
1642 VariableName,
1643 sizeof (DRIVER_SAMPLE_CONFIGURATION),
1644 (UINT8 *) Configuration,
1645 NULL
1646 );
1647 }
1648 FreePool (Configuration);
1649
1650 HiiCreateOneOfOpCode (
1651 StartOpCodeHandle, // Container for dynamic created opcodes
1652 0x8001, // Question ID (or call it "key")
1653 CONFIGURATION_VARSTORE_ID, // VarStore ID
1654 (UINT16) DYNAMIC_ONE_OF_VAR_OFFSET, // Offset in Buffer Storage
1655 STRING_TOKEN (STR_ONE_OF_PROMPT), // Question prompt text
1656 STRING_TOKEN (STR_ONE_OF_HELP), // Question help text
1657 EFI_IFR_FLAG_CALLBACK, // Question flag
1658 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
1659 OptionsOpCodeHandle, // Option Opcode list
1660 NULL // Default Opcode is NULl
1661 );
1662
1663 HiiCreateOrderedListOpCode (
1664 StartOpCodeHandle, // Container for dynamic created opcodes
1665 0x8002, // Question ID
1666 CONFIGURATION_VARSTORE_ID, // VarStore ID
1667 (UINT16) DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage
1668 STRING_TOKEN (STR_BOOT_OPTIONS), // Question prompt text
1669 STRING_TOKEN (STR_BOOT_OPTIONS), // Question help text
1670 EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
1671 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
1672 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value
1673 5, // Maximum container
1674 OptionsOpCodeHandle, // Option Opcode list
1675 NULL // Default Opcode is NULl
1676 );
1677
1678 HiiCreateTextOpCode (
1679 StartOpCodeHandle,
1680 STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
1681 STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
1682 STRING_TOKEN(STR_TEXT_SAMPLE_STRING)
1683 );
1684
1685 HiiCreateDateOpCode (
1686 StartOpCodeHandle,
1687 0x8004,
1688 0x0,
1689 0x0,
1690 STRING_TOKEN(STR_DATE_SAMPLE_HELP),
1691 STRING_TOKEN(STR_DATE_SAMPLE_HELP),
1692 0,
1693 QF_DATE_STORAGE_TIME,
1694 NULL
1695 );
1696
1697 HiiCreateTimeOpCode (
1698 StartOpCodeHandle,
1699 0x8005,
1700 0x0,
1701 0x0,
1702 STRING_TOKEN(STR_TIME_SAMPLE_HELP),
1703 STRING_TOKEN(STR_TIME_SAMPLE_HELP),
1704 0,
1705 QF_TIME_STORAGE_TIME,
1706 NULL
1707 );
1708
1709 HiiCreateGotoOpCode (
1710 StartOpCodeHandle, // Container for dynamic created opcodes
1711 1, // Target Form ID
1712 STRING_TOKEN (STR_GOTO_FORM1), // Prompt text
1713 STRING_TOKEN (STR_GOTO_HELP), // Help text
1714 0, // Question flag
1715 0x8003 // Question ID
1716 );
1717
1718 HiiUpdateForm (
1719 PrivateData->HiiHandle[0], // HII handle
1720 &gDriverSampleFormSetGuid, // Formset GUID
1721 0x1234, // Form ID
1722 StartOpCodeHandle, // Label for where to insert opcodes
1723 EndOpCodeHandle // Replace data
1724 );
1725
1726 HiiFreeOpCodeHandle (StartOpCodeHandle);
1727 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
1728 HiiFreeOpCodeHandle (EndOpCodeHandle);
1729 break;
1730
1731 case 0x2000:
1732 //
1733 // Only used to update the state.
1734 //
1735 if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0) &&
1736 (PrivateData->PasswordState == BROWSER_STATE_SET_PASSWORD)) {
1737 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1738 return EFI_INVALID_PARAMETER;
1739 }
1740
1741 //
1742 // When try to set a new password, user will be chanlleged with old password.
1743 // The Callback is responsible for validating old password input by user,
1744 // If Callback return EFI_SUCCESS, it indicates validation pass.
1745 //
1746 switch (PrivateData->PasswordState) {
1747 case BROWSER_STATE_VALIDATE_PASSWORD:
1748 Status = ValidatePassword (PrivateData, Value->string);
1749 if (Status == EFI_SUCCESS) {
1750 PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
1751 }
1752 break;
1753
1754 case BROWSER_STATE_SET_PASSWORD:
1755 Status = SetPassword (PrivateData, Value->string);
1756 PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1757 break;
1758
1759 default:
1760 break;
1761 }
1762
1763 break;
1764
1765 default:
1766 break;
1767 }
1768 }
1769 break;
1770
1771 case EFI_BROWSER_ACTION_CHANGED:
1772 switch (QuestionId) {
1773 case 0x1237:
1774 //
1775 // User press "Exit now", request Browser to exit
1776 //
1777 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
1778 break;
1779
1780 case 0x1238:
1781 //
1782 // User press "Save now", request Browser to save the uncommitted data.
1783 //
1784 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1785 break;
1786
1787 case 0x1241:
1788 case 0x1246:
1789 //
1790 // User press "Submit current form and Exit now", request Browser to submit current form and exit
1791 //
1792 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
1793 break;
1794
1795 case 0x1242:
1796 //
1797 // User press "Discard current form now", request Browser to discard the uncommitted data.
1798 //
1799 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD;
1800 break;
1801
1802 case 0x1243:
1803 //
1804 // User press "Submit current form now", request Browser to save the uncommitted data.
1805 //
1806 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
1807 break;
1808
1809 case 0x1244:
1810 case 0x1245:
1811 //
1812 // User press "Discard current form and Exit now", request Browser to discard the uncommitted data and exit.
1813 //
1814 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
1815 break;
1816
1817 case 0x1231:
1818 //
1819 // 1. Check to see whether system support keyword.
1820 //
1821 Status = PrivateData->HiiKeywordHandler->GetData (PrivateData->HiiKeywordHandler,
1822 L"NAMESPACE=x-UEFI-ns",
1823 L"KEYWORD=iSCSIBootEnable",
1824 &Progress,
1825 &ProgressErr,
1826 &Results
1827 );
1828 if (EFI_ERROR (Status)) {
1829 do {
1830 CreatePopUp (
1831 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1832 &Key,
1833 L"",
1834 L"This system not support this keyword!",
1835 L"Press ENTER to continue ...",
1836 L"",
1837 NULL
1838 );
1839 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1840
1841 Status = EFI_SUCCESS;
1842 break;
1843 }
1844
1845 //
1846 // 2. If system support this keyword, just try to change value.
1847 //
1848
1849 //
1850 // Change value from '0' to '1' or from '1' to '0'
1851 //
1852 TmpStr = StrStr (Results, L"&VALUE=");
1853 ASSERT (TmpStr != NULL);
1854 TmpStr += StrLen (L"&VALUE=");
1855 TmpStr++;
1856 if (*TmpStr == L'0') {
1857 *TmpStr = L'1';
1858 } else {
1859 *TmpStr = L'0';
1860 }
1861
1862 //
1863 // 3. Call the keyword handler protocol to change the value.
1864 //
1865 Status = PrivateData->HiiKeywordHandler->SetData (PrivateData->HiiKeywordHandler,
1866 Results,
1867 &Progress,
1868 &ProgressErr
1869 );
1870 if (EFI_ERROR (Status)) {
1871 do {
1872 CreatePopUp (
1873 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1874 &Key,
1875 L"",
1876 L"Set keyword to the system failed!",
1877 L"Press ENTER to continue ...",
1878 L"",
1879 NULL
1880 );
1881 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1882
1883 Status = EFI_SUCCESS;
1884 break;
1885 }
1886 break;
1887
1888 default:
1889 break;
1890 }
1891 break;
1892
1893 case EFI_BROWSER_ACTION_SUBMITTED:
1894 {
1895 if (QuestionId == 0x1250) {
1896 //
1897 // Sample CallBack for EFI_BROWSER_ACTION_SUBMITTED action:
1898 // Show up a pop-up to show SUBMITTED callback has been triggered.
1899 //
1900 do {
1901 CreatePopUp (
1902 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1903 &Key,
1904 L"",
1905 L"EfiVarstore value has been submitted!",
1906 L"Press ESC or ENTER to continue ...",
1907 L"",
1908 NULL
1909 );
1910 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1911 }
1912 }
1913 break;
1914
1915 default:
1916 Status = EFI_UNSUPPORTED;
1917 break;
1918 }
1919
1920 return Status;
1921 }
1922
1923 /**
1924 Main entry for this driver.
1925
1926 @param ImageHandle Image handle this driver.
1927 @param SystemTable Pointer to SystemTable.
1928
1929 @retval EFI_SUCESS This function always complete successfully.
1930
1931 **/
1932 EFI_STATUS
1933 EFIAPI
1934 DriverSampleInit (
1935 IN EFI_HANDLE ImageHandle,
1936 IN EFI_SYSTEM_TABLE *SystemTable
1937 )
1938 {
1939 EFI_STATUS Status;
1940 EFI_HII_HANDLE HiiHandle[2];
1941 EFI_SCREEN_DESCRIPTOR Screen;
1942 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
1943 EFI_HII_STRING_PROTOCOL *HiiString;
1944 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
1945 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1946 EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
1947 CHAR16 *NewString;
1948 UINTN BufferSize;
1949 DRIVER_SAMPLE_CONFIGURATION *Configuration;
1950 BOOLEAN ActionFlag;
1951 EFI_STRING ConfigRequestHdr;
1952 EFI_STRING NameRequestHdr;
1953 MY_EFI_VARSTORE_DATA *VarStoreConfig;
1954 EFI_INPUT_KEY HotKey;
1955 EDKII_FORM_BROWSER_EXTENSION_PROTOCOL *FormBrowserEx;
1956
1957 //
1958 // Initialize the local variables.
1959 //
1960 ConfigRequestHdr = NULL;
1961 NewString = NULL;
1962
1963 //
1964 // Initialize screen dimensions for SendForm().
1965 // Remove 3 characters from top and bottom
1966 //
1967 ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
1968 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
1969
1970 Screen.TopRow = 3;
1971 Screen.BottomRow = Screen.BottomRow - 3;
1972
1973 //
1974 // Initialize driver private data
1975 //
1976 mPrivateData = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
1977 if (mPrivateData == NULL) {
1978 return EFI_OUT_OF_RESOURCES;
1979 }
1980
1981 mPrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
1982
1983 mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
1984 mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
1985 mPrivateData->ConfigAccess.Callback = DriverCallback;
1986 mPrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
1987
1988 //
1989 // Locate Hii Database protocol
1990 //
1991 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
1992 if (EFI_ERROR (Status)) {
1993 return Status;
1994 }
1995 mPrivateData->HiiDatabase = HiiDatabase;
1996
1997 //
1998 // Locate HiiString protocol
1999 //
2000 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
2001 if (EFI_ERROR (Status)) {
2002 return Status;
2003 }
2004 mPrivateData->HiiString = HiiString;
2005
2006 //
2007 // Locate Formbrowser2 protocol
2008 //
2009 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
2010 if (EFI_ERROR (Status)) {
2011 return Status;
2012 }
2013 mPrivateData->FormBrowser2 = FormBrowser2;
2014
2015 //
2016 // Locate ConfigRouting protocol
2017 //
2018 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
2019 if (EFI_ERROR (Status)) {
2020 return Status;
2021 }
2022 mPrivateData->HiiConfigRouting = HiiConfigRouting;
2023
2024 //
2025 // Locate keyword handler protocol
2026 //
2027 Status = gBS->LocateProtocol (&gEfiConfigKeywordHandlerProtocolGuid, NULL, (VOID **) &HiiKeywordHandler);
2028 if (EFI_ERROR (Status)) {
2029 return Status;
2030 }
2031 mPrivateData->HiiKeywordHandler = HiiKeywordHandler;
2032
2033 Status = gBS->InstallMultipleProtocolInterfaces (
2034 &DriverHandle[0],
2035 &gEfiDevicePathProtocolGuid,
2036 &mHiiVendorDevicePath0,
2037 &gEfiHiiConfigAccessProtocolGuid,
2038 &mPrivateData->ConfigAccess,
2039 NULL
2040 );
2041 ASSERT_EFI_ERROR (Status);
2042
2043 mPrivateData->DriverHandle[0] = DriverHandle[0];
2044
2045 //
2046 // Publish our HII data
2047 //
2048 HiiHandle[0] = HiiAddPackages (
2049 &gDriverSampleFormSetGuid,
2050 DriverHandle[0],
2051 DriverSampleStrings,
2052 VfrBin,
2053 NULL
2054 );
2055 if (HiiHandle[0] == NULL) {
2056 return EFI_OUT_OF_RESOURCES;
2057 }
2058
2059 mPrivateData->HiiHandle[0] = HiiHandle[0];
2060
2061 //
2062 // Publish another Fromset
2063 //
2064 Status = gBS->InstallMultipleProtocolInterfaces (
2065 &DriverHandle[1],
2066 &gEfiDevicePathProtocolGuid,
2067 &mHiiVendorDevicePath1,
2068 &gEfiHiiConfigAccessProtocolGuid,
2069 &mPrivateData->ConfigAccess,
2070 NULL
2071 );
2072 ASSERT_EFI_ERROR (Status);
2073
2074 mPrivateData->DriverHandle[1] = DriverHandle[1];
2075
2076 HiiHandle[1] = HiiAddPackages (
2077 &gDriverSampleInventoryGuid,
2078 DriverHandle[1],
2079 DriverSampleStrings,
2080 InventoryBin,
2081 NULL
2082 );
2083 if (HiiHandle[1] == NULL) {
2084 DriverSampleUnload (ImageHandle);
2085 return EFI_OUT_OF_RESOURCES;
2086 }
2087
2088 mPrivateData->HiiHandle[1] = HiiHandle[1];
2089
2090 //
2091 // Update the device path string.
2092 //
2093 NewString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)&mHiiVendorDevicePath0, FALSE, FALSE);
2094 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_DEVICE_PATH), NewString, NULL) == 0) {
2095 DriverSampleUnload (ImageHandle);
2096 return EFI_OUT_OF_RESOURCES;
2097 }
2098 if (NewString != NULL) {
2099 FreePool (NewString);
2100 }
2101
2102 //
2103 // Very simple example of how one would update a string that is already
2104 // in the HII database
2105 //
2106 NewString = L"700 Mhz";
2107
2108 if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString, NULL) == 0) {
2109 DriverSampleUnload (ImageHandle);
2110 return EFI_OUT_OF_RESOURCES;
2111 }
2112
2113 HiiSetString (HiiHandle[0], 0, NewString, NULL);
2114
2115 //
2116 // Initialize Name/Value name String ID
2117 //
2118 mPrivateData->NameStringId[0] = STR_NAME_VALUE_VAR_NAME0;
2119 mPrivateData->NameStringId[1] = STR_NAME_VALUE_VAR_NAME1;
2120 mPrivateData->NameStringId[2] = STR_NAME_VALUE_VAR_NAME2;
2121
2122 //
2123 // Initialize configuration data
2124 //
2125 Configuration = &mPrivateData->Configuration;
2126 ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
2127
2128 //
2129 // Try to read NV config EFI variable first
2130 //
2131 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, DriverHandle[0]);
2132 ASSERT (ConfigRequestHdr != NULL);
2133
2134 NameRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, NULL, DriverHandle[0]);
2135 ASSERT (NameRequestHdr != NULL);
2136
2137 BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
2138 Status = gRT->GetVariable (VariableName, &gDriverSampleFormSetGuid, NULL, &BufferSize, Configuration);
2139 if (EFI_ERROR (Status)) {
2140 //
2141 // Store zero data Buffer Storage to EFI variable
2142 //
2143 Status = gRT->SetVariable(
2144 VariableName,
2145 &gDriverSampleFormSetGuid,
2146 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
2147 sizeof (DRIVER_SAMPLE_CONFIGURATION),
2148 Configuration
2149 );
2150 if (EFI_ERROR (Status)) {
2151 DriverSampleUnload (ImageHandle);
2152 return Status;
2153 }
2154 //
2155 // EFI variable for NV config doesn't exit, we should build this variable
2156 // based on default values stored in IFR
2157 //
2158 ActionFlag = HiiSetToDefaults (NameRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2159 if (!ActionFlag) {
2160 DriverSampleUnload (ImageHandle);
2161 return EFI_INVALID_PARAMETER;
2162 }
2163
2164 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2165 if (!ActionFlag) {
2166 DriverSampleUnload (ImageHandle);
2167 return EFI_INVALID_PARAMETER;
2168 }
2169 } else {
2170 //
2171 // EFI variable does exist and Validate Current Setting
2172 //
2173 ActionFlag = HiiValidateSettings (NameRequestHdr);
2174 if (!ActionFlag) {
2175 DriverSampleUnload (ImageHandle);
2176 return EFI_INVALID_PARAMETER;
2177 }
2178
2179 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
2180 if (!ActionFlag) {
2181 DriverSampleUnload (ImageHandle);
2182 return EFI_INVALID_PARAMETER;
2183 }
2184 }
2185 FreePool (ConfigRequestHdr);
2186
2187 //
2188 // Initialize efi varstore configuration data
2189 //
2190 VarStoreConfig = &mPrivateData->VarStoreConfig;
2191 ZeroMem (VarStoreConfig, sizeof (MY_EFI_VARSTORE_DATA));
2192
2193 ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, MyEfiVar, DriverHandle[0]);
2194 ASSERT (ConfigRequestHdr != NULL);
2195
2196 BufferSize = sizeof (MY_EFI_VARSTORE_DATA);
2197 Status = gRT->GetVariable (MyEfiVar, &gDriverSampleFormSetGuid, NULL, &BufferSize, VarStoreConfig);
2198 if (EFI_ERROR (Status)) {
2199 //
2200 // Store zero data to EFI variable Storage.
2201 //
2202 Status = gRT->SetVariable(
2203 MyEfiVar,
2204 &gDriverSampleFormSetGuid,
2205 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
2206 sizeof (MY_EFI_VARSTORE_DATA),
2207 VarStoreConfig
2208 );
2209 if (EFI_ERROR (Status)) {
2210 DriverSampleUnload (ImageHandle);
2211 return Status;
2212 }
2213 //
2214 // EFI variable for NV config doesn't exit, we should build this variable
2215 // based on default values stored in IFR
2216 //
2217 ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
2218 if (!ActionFlag) {
2219 DriverSampleUnload (ImageHandle);
2220 return EFI_INVALID_PARAMETER;
2221 }
2222 } else {
2223 //
2224 // EFI variable does exist and Validate Current Setting
2225 //
2226 ActionFlag = HiiValidateSettings (ConfigRequestHdr);
2227 if (!ActionFlag) {
2228 DriverSampleUnload (ImageHandle);
2229 return EFI_INVALID_PARAMETER;
2230 }
2231 }
2232 FreePool (ConfigRequestHdr);
2233
2234 Status = gBS->CreateEventEx (
2235 EVT_NOTIFY_SIGNAL,
2236 TPL_NOTIFY,
2237 DriverSampleInternalEmptyFunction,
2238 NULL,
2239 &gEfiIfrRefreshIdOpGuid,
2240 &mEvent
2241 );
2242 ASSERT_EFI_ERROR (Status);
2243
2244 //
2245 // Example of how to use BrowserEx protocol to register HotKey.
2246 //
2247 Status = gBS->LocateProtocol (&gEdkiiFormBrowserExProtocolGuid, NULL, (VOID **) &FormBrowserEx);
2248 if (!EFI_ERROR (Status)) {
2249 //
2250 // First unregister the default hot key F9 and F10.
2251 //
2252 HotKey.UnicodeChar = CHAR_NULL;
2253 HotKey.ScanCode = SCAN_F9;
2254 FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
2255 HotKey.ScanCode = SCAN_F10;
2256 FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL);
2257
2258 //
2259 // Register the default HotKey F9 and F10 again.
2260 //
2261 HotKey.ScanCode = SCAN_F10;
2262 NewString = HiiGetString (mPrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
2263 ASSERT (NewString != NULL);
2264 FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
2265 HotKey.ScanCode = SCAN_F9;
2266 NewString = HiiGetString (mPrivateData->HiiHandle[0], STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
2267 ASSERT (NewString != NULL);
2268 FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
2269 }
2270
2271 //
2272 // In default, this driver is built into Flash device image,
2273 // the following code doesn't run.
2274 //
2275
2276 //
2277 // Example of how to display only the item we sent to HII
2278 // When this driver is not built into Flash device image,
2279 // it need to call SendForm to show front page by itself.
2280 //
2281 if (DISPLAY_ONLY_MY_ITEM <= 1) {
2282 //
2283 // Have the browser pull out our copy of the data, and only display our data
2284 //
2285 Status = FormBrowser2->SendForm (
2286 FormBrowser2,
2287 &(HiiHandle[DISPLAY_ONLY_MY_ITEM]),
2288 1,
2289 NULL,
2290 0,
2291 NULL,
2292 NULL
2293 );
2294
2295 HiiRemovePackages (HiiHandle[0]);
2296
2297 HiiRemovePackages (HiiHandle[1]);
2298 }
2299
2300 return EFI_SUCCESS;
2301 }
2302
2303 /**
2304 Unloads the application and its installed protocol.
2305
2306 @param[in] ImageHandle Handle that identifies the image to be unloaded.
2307
2308 @retval EFI_SUCCESS The image has been unloaded.
2309 **/
2310 EFI_STATUS
2311 EFIAPI
2312 DriverSampleUnload (
2313 IN EFI_HANDLE ImageHandle
2314 )
2315 {
2316 UINTN Index;
2317
2318 ASSERT (mPrivateData != NULL);
2319
2320 if (DriverHandle[0] != NULL) {
2321 gBS->UninstallMultipleProtocolInterfaces (
2322 DriverHandle[0],
2323 &gEfiDevicePathProtocolGuid,
2324 &mHiiVendorDevicePath0,
2325 &gEfiHiiConfigAccessProtocolGuid,
2326 &mPrivateData->ConfigAccess,
2327 NULL
2328 );
2329 DriverHandle[0] = NULL;
2330 }
2331
2332 if (DriverHandle[1] != NULL) {
2333 gBS->UninstallMultipleProtocolInterfaces (
2334 DriverHandle[1],
2335 &gEfiDevicePathProtocolGuid,
2336 &mHiiVendorDevicePath1,
2337 &gEfiHiiConfigAccessProtocolGuid,
2338 &mPrivateData->ConfigAccess,
2339 NULL
2340 );
2341 DriverHandle[1] = NULL;
2342 }
2343
2344 if (mPrivateData->HiiHandle[0] != NULL) {
2345 HiiRemovePackages (mPrivateData->HiiHandle[0]);
2346 }
2347
2348 if (mPrivateData->HiiHandle[1] != NULL) {
2349 HiiRemovePackages (mPrivateData->HiiHandle[1]);
2350 }
2351
2352 for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) {
2353 if (mPrivateData->NameValueName[Index] != NULL) {
2354 FreePool (mPrivateData->NameValueName[Index]);
2355 }
2356 }
2357 FreePool (mPrivateData);
2358 mPrivateData = NULL;
2359
2360 gBS->CloseEvent (mEvent);
2361
2362 return EFI_SUCCESS;
2363 }