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