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