2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 This is an example of how a driver might export data to the HII protocol to be
17 later utilized by the Setup Protocol
21 #include "DriverSample.h"
23 #define DISPLAY_ONLY_MY_ITEM 0x0001
25 #define STRING_PACK_GUID \
27 0x8160a85f, 0x934d, 0x468b, { 0xa2, 0x35, 0x72, 0x89, 0x59, 0x14, 0xf6, 0xfc } \
30 EFI_GUID mFormSetGuid
= FORMSET_GUID
;
31 EFI_GUID mStringPackGuid
= STRING_PACK_GUID
;
36 IN EFI_FORM_CALLBACK_PROTOCOL
*This
,
38 IN EFI_IFR_DATA_ARRAY
*Data
,
39 OUT EFI_HII_CALLBACK_PACKET
**Packet
45 This is the function that is called to provide results data to the driver. This data
46 consists of a unique key which is used to identify what data is either being passed back
51 KeyValue - A unique value which is sent to the original exporting driver so that it
52 can identify the type of data to expect. The format of the data tends to
53 vary based on the op-code that geerated the callback.
55 Data - A pointer to the data being sent to the original exporting driver.
61 EFI_CALLBACK_INFO
*Private
;
62 EFI_HII_UPDATE_DATA
*UpdateData
;
65 EFI_HII_CALLBACK_PACKET
*DataPacket
;
67 CHAR16 VariableName
[40];
68 STATIC UINT16 QuestionId
= 0;
69 IFR_OPTION
*OptionList
;
73 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
76 // This should tell me the first offset AFTER the end of the compiled NV map
77 // If op-code results are not going to be saved to NV locations ensure the QuestionId
78 // is beyond the end of the NVRAM mapping.
80 if (QuestionId
== 0) {
81 QuestionId
= sizeof (MyIfrNVData
);
84 ZeroMem (VariableName
, (sizeof (CHAR16
) * 40));
89 // Create a small boot order list
91 QuestionId
= (UINT16
) ((UINTN
) (&NVStruc
.BootOrder
) - (UINTN
) (&NVStruc
));
94 // Need some memory for OptionList. Allow for up to 8 options.
96 OptionList
= AllocateZeroPool (sizeof (IFR_OPTION
) * 8);
97 ASSERT (OptionList
!= NULL
);
100 // Allocate space for creation of Buffer
102 UpdateData
= AllocateZeroPool (0x1000);
103 ASSERT (UpdateData
!= NULL
);
106 // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
107 // so we don't have to keep track of how many op-codes we added or subtracted. The rules for removal
108 // of op-codes are simply that the removal will always stop as soon as a label or the end of a form is
109 // encountered. Therefore, giving a large obnoxious count such as below takes care of other complexities.
111 UpdateData
->DataCount
= 0xFF;
114 // Delete set of op-codes
116 Private
->Hii
->UpdateForm (
118 Private
->RegisteredHandle
,
119 (EFI_FORM_LABEL
) 0x2222,
120 FALSE
, // If we aren't adding, we are deleting
127 for (Index
= 0; Index
< 3; Index
++) {
128 OptionList
[Index
].StringToken
= (UINT16
) (STR_BOOT_OPTION1
+ Index
);
129 OptionList
[Index
].Value
= (UINT16
) (Index
+ 1);
130 OptionList
[Index
].Flags
= RESET_REQUIRED
;
133 CreateOrderedListOpCode (
134 QuestionId
, // Question ID
136 (UINT16
) STRING_TOKEN (STR_BOOT_OPTIONS
), // Token value for the Prompt
137 (UINT16
) STRING_TOKEN (STR_NULL_STRING
), // Token value for the Help
140 &UpdateData
->Data
// Buffer location to place op-codes
144 // For one-of/ordered lists commands, they really consist of 2 op-codes (a header and a footer)
145 // Each option within a one-of/ordered list is also an op-code
146 // So this example has 5 op-codes it is adding since we have a one-of header + 3 options + one-of footer
148 UpdateData
->DataCount
= 0x5;
153 Private
->Hii
->UpdateForm (
155 Private
->RegisteredHandle
,
156 (EFI_FORM_LABEL
) 0x2222,
161 gBS
->FreePool (UpdateData
);
162 gBS
->FreePool (OptionList
);
167 // Create a large boot order list
169 QuestionId
= (UINT16
) ((UINTN
) (&NVStruc
.BootOrder
) - (UINTN
) (&NVStruc
));
172 // Need some memory for OptionList. Allow for up to 8 options.
174 OptionList
= AllocateZeroPool (sizeof (IFR_OPTION
) * 8);
175 ASSERT (OptionList
!= NULL
);
178 // Allocate space for creation of Buffer
180 UpdateData
= AllocateZeroPool (0x1000);
181 ASSERT (UpdateData
!= NULL
);
184 // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
185 // so we don't have to keep track of how many op-codes we added or subtracted
187 UpdateData
->DataCount
= 0xFF;
190 // Delete one op-code
192 Private
->Hii
->UpdateForm (
194 Private
->RegisteredHandle
,
195 (EFI_FORM_LABEL
) 0x2222,
203 for (Index
= 0; Index
< 4; Index
++) {
204 OptionList
[Index
].StringToken
= (UINT16
) (STR_BOOT_OPTION1
+ Index
);
205 OptionList
[Index
].Value
= (UINT16
) (Index
+ 1);
206 OptionList
[Index
].Flags
= RESET_REQUIRED
;
209 CreateOrderedListOpCode (
210 QuestionId
, // Question ID
212 (UINT16
) STRING_TOKEN (STR_BOOT_OPTIONS
), // Token value for the Prompt
213 (UINT16
) STRING_TOKEN (STR_NULL_STRING
), // Token value for the Help
216 &UpdateData
->Data
// Buffer location to place op-codes
220 // For one-of commands, they really consist of 2 op-codes (a header and a footer)
221 // Each option within a one-of is also an op-code
222 // So this example has 6 op-codes it is adding since we have a one-of header + 4 options + one-of footer
224 UpdateData
->DataCount
= 0x6;
229 Private
->Hii
->UpdateForm (
231 Private
->RegisteredHandle
,
232 (EFI_FORM_LABEL
) 0x2222,
237 gBS
->FreePool (UpdateData
);
238 gBS
->FreePool (OptionList
);
243 // Allocate space for creation of Buffer
245 QuestionId
= (UINT16
) ((UINTN
) (&NVStruc
.DynamicCheck
) - (UINTN
) (&NVStruc
));
246 Status
= gBS
->AllocatePool (
249 (VOID
**) &UpdateData
251 ASSERT_EFI_ERROR (Status
);
253 ZeroMem (UpdateData
, 0x1000);
255 Location
= (UINT8
*) &UpdateData
->Data
;
257 UpdateData
->FormSetUpdate
= TRUE
;
258 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Private
->CallbackHandle
;
259 UpdateData
->FormUpdate
= FALSE
;
260 UpdateData
->FormTitle
= 0;
261 UpdateData
->DataCount
= 2;
265 STR_GOTO_FORM1
, // Token value for the Prompt
269 &UpdateData
->Data
// Buffer location to place op-codes
272 Location
= Location
+ ((EFI_IFR_OP_HEADER
*) &UpdateData
->Data
)->Length
;
274 CreateCheckBoxOpCode (
275 QuestionId
, // Question ID
276 1, // Data width (BOOLEAN = 1)
277 (UINT16
) STRING_TOKEN (STR_CHECK_DYNAMIC_PROMPT
), // Token value for the Prompt
278 (UINT16
) STRING_TOKEN (STR_CHECK_DYNAMIC_HELP
), // Token value for the Help
279 EFI_IFR_FLAG_INTERACTIVE
, // Flags
281 Location
// Buffer location to place op-codes
284 Private
->Hii
->UpdateForm (
286 Private
->RegisteredHandle
,
287 (EFI_FORM_LABEL
) 0x1234,
292 gBS
->FreePool (UpdateData
);
298 // Allocate space for creation of Buffer
300 Status
= gBS
->AllocatePool (
305 ASSERT_EFI_ERROR (Status
);
307 ZeroMem (UpdateData
, 0x1000);
310 // Initialize DataPacket with information intended to remove all
311 // previously created op-codes in the dynamic page
313 UpdateData
->FormSetUpdate
= FALSE
;
314 UpdateData
->FormCallbackHandle
= 0;
315 UpdateData
->FormUpdate
= FALSE
;
316 UpdateData
->FormTitle
= 0;
318 // Unlikely to be more than 0xff op-codes in the dynamic page to remove
320 UpdateData
->DataCount
= 0xff;
321 UpdateData
->Data
= NULL
;
324 // Remove all op-codes from dynamic page
326 Private
->Hii
->UpdateForm (
328 Private
->RegisteredHandle
,
329 (EFI_FORM_LABEL
) 0x1234, // Label 0x1234
330 FALSE
, // Remove Op-codes (will never remove form/endform)
331 UpdateData
// Significant value is UpdateData->DataCount
334 UpdateData
->FormSetUpdate
= FALSE
;
335 UpdateData
->FormCallbackHandle
= 0;
336 UpdateData
->FormUpdate
= FALSE
;
337 UpdateData
->FormTitle
= 0;
338 UpdateData
->DataCount
= 1;
342 STR_GOTO_FORM1
, // Token value for the Prompt
346 &UpdateData
->Data
// Buffer location to place op-codes
349 Private
->Hii
->UpdateForm (
351 Private
->RegisteredHandle
,
352 (EFI_FORM_LABEL
) 0x1234,
357 gBS
->FreePool (UpdateData
);
362 // If I hit the checkbox, I enter this case statement...
365 // Since I am returning an error (for test purposes) I need to pass in the string for the error
366 // I will allocate space for the return value. If an error occurs (which is the case) I can simply return
367 // an error and fill in the string parameter, otherwise, I will return information in the DataArray structure.
368 // The browser will free this packet structure
370 Status
= gBS
->AllocatePool (
372 sizeof (EFI_HII_CALLBACK_PACKET
) + sizeof (SAMPLE_STRING
) + 2,
375 ASSERT_EFI_ERROR (Status
);
377 ZeroMem (*Packet
, sizeof (EFI_HII_CALLBACK_PACKET
) + sizeof (SAMPLE_STRING
) + 2);
380 // Assign the buffer address to DataPacket
382 DataPacket
= *Packet
;
384 StrCpy (DataPacket
->String
, (CHAR16
*) SAMPLE_STRING
);
385 return EFI_DEVICE_ERROR
;
389 Status
= gBS
->AllocatePool (
391 sizeof (EFI_HII_CALLBACK_PACKET
) + 2,
394 ASSERT_EFI_ERROR (Status
);
396 ZeroMem (*Packet
, sizeof (EFI_HII_CALLBACK_PACKET
) + 2);
399 // Assign the buffer address to DataPacket
401 DataPacket
= *Packet
;
403 DataPacket
->DataArray
.EntryCount
= 1;
404 DataPacket
->DataArray
.NvRamMap
= NULL
;
405 ((EFI_IFR_DATA_ENTRY
*) (&DataPacket
->DataArray
+ 1))->Flags
= EXIT_REQUIRED
;
410 UnicodeSPrint (VariableName
, 0x80, (CHAR16
*) L
"%d", VAR_EQ_TEST_NAME
);
412 Status
= gRT
->SetVariable (
415 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
423 UnicodeSPrint (VariableName
, 0x80, (CHAR16
*) L
"%d", VAR_EQ_TEST_NAME
);
425 Status
= gRT
->SetVariable (
428 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
436 UnicodeSPrint (VariableName
, 0x80, (CHAR16
*) L
"%d", VAR_EQ_TEST_NAME
);
438 Status
= gRT
->SetVariable (
441 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
457 IN EFI_HANDLE ImageHandle
,
458 IN EFI_SYSTEM_TABLE
*SystemTable
462 EFI_HII_PROTOCOL
*Hii
;
464 // EFI_FORM_BROWSER_PROTOCOL *FormConfig;
466 EFI_HII_PACKAGES
*PackageList
;
467 EFI_HII_HANDLE HiiHandle
;
468 STRING_REF TokenToUpdate
;
469 STRING_REF TokenToUpdate2
;
470 STRING_REF TokenToUpdate3
;
472 EFI_HII_UPDATE_DATA
*UpdateData
;
473 EFI_CALLBACK_INFO
*CallbackInfo
;
475 EFI_SCREEN_DESCRIPTOR Screen
;
477 ZeroMem (&Screen
, sizeof (EFI_SCREEN_DESCRIPTOR
));
479 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &Screen
.RightColumn
, &Screen
.BottomRow
);
482 // Remove 3 characters from top and bottom
485 Screen
.BottomRow
= Screen
.BottomRow
- 3;
488 // There should only be one HII protocol
490 Status
= gBS
->LocateProtocol (
491 &gEfiHiiProtocolGuid
,
495 if (EFI_ERROR (Status
)) {
501 // There should only be one Form Configuration protocol
503 Status = gBS->LocateProtocol (
504 &gEfiFormBrowserProtocolGuid,
508 if (EFI_ERROR (Status)) {
512 Status
= gBS
->AllocatePool (
514 sizeof (EFI_CALLBACK_INFO
),
515 (VOID
**) &CallbackInfo
517 if (EFI_ERROR (Status
)) {
521 CallbackInfo
->Signature
= EFI_CALLBACK_INFO_SIGNATURE
;
522 CallbackInfo
->Hii
= Hii
;
525 // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator
527 CallbackInfo
->DriverCallback
.NvRead
= NULL
;
528 CallbackInfo
->DriverCallback
.NvWrite
= NULL
;
529 CallbackInfo
->DriverCallback
.Callback
= DriverCallback
;
532 // Install protocol interface
535 Status
= gBS
->InstallProtocolInterface (
537 &gEfiFormCallbackProtocolGuid
,
538 EFI_NATIVE_INTERFACE
,
539 &CallbackInfo
->DriverCallback
542 ASSERT_EFI_ERROR (Status
);
544 CallbackInfo
->CallbackHandle
= Handle
;
546 PackageList
= PreparePackages (1, &mStringPackGuid
, DriverSampleStrings
);
547 Status
= Hii
->NewPack (Hii
, PackageList
, &HiiHandle
);
548 gBS
->FreePool (PackageList
);
550 PackageList
= PreparePackages (1, &mStringPackGuid
, InventoryBin
);
551 Status
= Hii
->NewPack (Hii
, PackageList
, &HiiHandle
);
552 gBS
->FreePool (PackageList
);
554 PackageList
= PreparePackages (1, &mStringPackGuid
, VfrBin
);
555 Status
= Hii
->NewPack (Hii
, PackageList
, &HiiHandle
);
556 gBS
->FreePool (PackageList
);
558 CallbackInfo
->RegisteredHandle
= HiiHandle
;
561 // Very simple example of how one would update a string that is already
562 // in the HII database
564 TokenToUpdate
= (STRING_REF
) STR_CPU_STRING2
;
565 NewString
= (CHAR16
*) L
"700 Mhz";
567 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate
, NewString
);
570 // Add a string - if 0 will be updated with new Token number
572 TokenToUpdate
= (STRING_REF
) 0;
575 // Add a string - if 0 will be updated with new Token number
577 TokenToUpdate2
= (STRING_REF
) 0;
580 // Add a string - if 0 will be updated with new Token number
582 TokenToUpdate3
= (STRING_REF
) 0;
584 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate
, (CHAR16
*) L
"Desired Speed");
585 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate2
, (CHAR16
*) L
"5 Thz");
586 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate3
, (CHAR16
*) L
"This is next year's desired speed - right?");
589 // Allocate space for creation of Buffer
591 Status
= gBS
->AllocatePool (
594 (VOID
**) &UpdateData
596 ASSERT_EFI_ERROR (Status
);
598 ZeroMem (UpdateData
, 0x1000);
601 // Flag update pending in FormSet
603 UpdateData
->FormSetUpdate
= TRUE
;
605 // Register CallbackHandle data for FormSet
607 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) CallbackInfo
->CallbackHandle
;
608 UpdateData
->FormUpdate
= FALSE
;
609 UpdateData
->FormTitle
= 0;
610 UpdateData
->DataCount
= 1;
612 CreateTextOpCode (TokenToUpdate
, TokenToUpdate2
, TokenToUpdate3
, 0, 0, &UpdateData
->Data
);
614 Hii
->UpdateForm (Hii
, HiiHandle
, (EFI_FORM_LABEL
) 100, TRUE
, UpdateData
);
616 gBS
->FreePool (UpdateData
);
619 // Example of how to display only the item we sent to HII
621 if (DISPLAY_ONLY_MY_ITEM
== 0x0001) {
623 // Have the browser pull out our copy of the data, and only display our data
625 // Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL);
629 // Have the browser pull out all the data in the HII Database and display it.
631 // Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL);
635 if (EFI_ERROR (Status
)) {