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
;
37 IN EFI_FORM_CALLBACK_PROTOCOL
*This
,
39 IN EFI_IFR_DATA_ARRAY
*Data
,
40 OUT EFI_HII_CALLBACK_PACKET
**Packet
46 This is the function that is called to provide results data to the driver. This data
47 consists of a unique key which is used to identify what data is either being passed back
52 KeyValue - A unique value which is sent to the original exporting driver so that it
53 can identify the type of data to expect. The format of the data tends to
54 vary based on the op-code that geerated the callback.
56 Data - A pointer to the data being sent to the original exporting driver.
62 EFI_CALLBACK_INFO
*Private
;
63 EFI_HII_UPDATE_DATA
*UpdateData
;
66 EFI_HII_CALLBACK_PACKET
*DataPacket
;
68 CHAR16 VariableName
[40];
69 STATIC UINT16 QuestionId
= 0;
70 IFR_OPTION
*OptionList
;
74 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
77 // This should tell me the first offset AFTER the end of the compiled NV map
78 // If op-code results are not going to be saved to NV locations ensure the QuestionId
79 // is beyond the end of the NVRAM mapping.
81 if (QuestionId
== 0) {
82 QuestionId
= sizeof (MyIfrNVData
);
85 ZeroMem (VariableName
, (sizeof (CHAR16
) * 40));
90 // Create a small boot order list
92 QuestionId
= (UINT16
) ((UINTN
) (&NVStruc
.BootOrder
) - (UINTN
) (&NVStruc
));
95 // Need some memory for OptionList. Allow for up to 8 options.
97 OptionList
= AllocateZeroPool (sizeof (IFR_OPTION
) * 8);
98 ASSERT (OptionList
!= NULL
);
101 // Allocate space for creation of Buffer
103 UpdateData
= AllocateZeroPool (0x1000);
104 ASSERT (UpdateData
!= NULL
);
107 // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
108 // so we don't have to keep track of how many op-codes we added or subtracted. The rules for removal
109 // of op-codes are simply that the removal will always stop as soon as a label or the end of a form is
110 // encountered. Therefore, giving a large obnoxious count such as below takes care of other complexities.
112 UpdateData
->DataCount
= 0xFF;
115 // Delete set of op-codes
117 Private
->Hii
->UpdateForm (
119 Private
->RegisteredHandle
,
120 (EFI_FORM_LABEL
) 0x2222,
121 FALSE
, // If we aren't adding, we are deleting
128 for (Index
= 0; Index
< 3; Index
++) {
129 OptionList
[Index
].StringToken
= (UINT16
) (STR_BOOT_OPTION1
+ Index
);
130 OptionList
[Index
].Value
= (UINT16
) (Index
+ 1);
131 OptionList
[Index
].Flags
= RESET_REQUIRED
;
134 CreateOrderedListOpCode (
135 QuestionId
, // Question ID
137 (UINT16
) STRING_TOKEN (STR_BOOT_OPTIONS
), // Token value for the Prompt
138 (UINT16
) STRING_TOKEN (STR_NULL_STRING
), // Token value for the Help
141 &UpdateData
->Data
// Buffer location to place op-codes
145 // For one-of/ordered lists commands, they really consist of 2 op-codes (a header and a footer)
146 // Each option within a one-of/ordered list is also an op-code
147 // So this example has 5 op-codes it is adding since we have a one-of header + 3 options + one-of footer
149 UpdateData
->DataCount
= 0x5;
154 Private
->Hii
->UpdateForm (
156 Private
->RegisteredHandle
,
157 (EFI_FORM_LABEL
) 0x2222,
162 gBS
->FreePool (UpdateData
);
163 gBS
->FreePool (OptionList
);
168 // Create a large boot order list
170 QuestionId
= (UINT16
) ((UINTN
) (&NVStruc
.BootOrder
) - (UINTN
) (&NVStruc
));
173 // Need some memory for OptionList. Allow for up to 8 options.
175 OptionList
= AllocateZeroPool (sizeof (IFR_OPTION
) * 8);
176 ASSERT (OptionList
!= NULL
);
179 // Allocate space for creation of Buffer
181 UpdateData
= AllocateZeroPool (0x1000);
182 ASSERT (UpdateData
!= NULL
);
185 // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
186 // so we don't have to keep track of how many op-codes we added or subtracted
188 UpdateData
->DataCount
= 0xFF;
191 // Delete one op-code
193 Private
->Hii
->UpdateForm (
195 Private
->RegisteredHandle
,
196 (EFI_FORM_LABEL
) 0x2222,
204 for (Index
= 0; Index
< 4; Index
++) {
205 OptionList
[Index
].StringToken
= (UINT16
) (STR_BOOT_OPTION1
+ Index
);
206 OptionList
[Index
].Value
= (UINT16
) (Index
+ 1);
207 OptionList
[Index
].Flags
= RESET_REQUIRED
;
210 CreateOrderedListOpCode (
211 QuestionId
, // Question ID
213 (UINT16
) STRING_TOKEN (STR_BOOT_OPTIONS
), // Token value for the Prompt
214 (UINT16
) STRING_TOKEN (STR_NULL_STRING
), // Token value for the Help
217 &UpdateData
->Data
// Buffer location to place op-codes
221 // For one-of commands, they really consist of 2 op-codes (a header and a footer)
222 // Each option within a one-of is also an op-code
223 // So this example has 6 op-codes it is adding since we have a one-of header + 4 options + one-of footer
225 UpdateData
->DataCount
= 0x6;
230 Private
->Hii
->UpdateForm (
232 Private
->RegisteredHandle
,
233 (EFI_FORM_LABEL
) 0x2222,
238 gBS
->FreePool (UpdateData
);
239 gBS
->FreePool (OptionList
);
244 // Allocate space for creation of Buffer
246 QuestionId
= (UINT16
) ((UINTN
) (&NVStruc
.DynamicCheck
) - (UINTN
) (&NVStruc
));
247 Status
= gBS
->AllocatePool (
250 (VOID
**) &UpdateData
252 ASSERT_EFI_ERROR (Status
);
254 ZeroMem (UpdateData
, 0x1000);
256 Location
= (UINT8
*) &UpdateData
->Data
;
258 UpdateData
->FormSetUpdate
= TRUE
;
259 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Private
->CallbackHandle
;
260 UpdateData
->FormUpdate
= FALSE
;
261 UpdateData
->FormTitle
= 0;
262 UpdateData
->DataCount
= 2;
266 STR_GOTO_FORM1
, // Token value for the Prompt
270 &UpdateData
->Data
// Buffer location to place op-codes
273 Location
= Location
+ ((EFI_IFR_OP_HEADER
*) &UpdateData
->Data
)->Length
;
275 CreateCheckBoxOpCode (
276 QuestionId
, // Question ID
277 1, // Data width (BOOLEAN = 1)
278 (UINT16
) STRING_TOKEN (STR_CHECK_DYNAMIC_PROMPT
), // Token value for the Prompt
279 (UINT16
) STRING_TOKEN (STR_CHECK_DYNAMIC_HELP
), // Token value for the Help
280 EFI_IFR_FLAG_INTERACTIVE
, // Flags
282 Location
// Buffer location to place op-codes
285 Private
->Hii
->UpdateForm (
287 Private
->RegisteredHandle
,
288 (EFI_FORM_LABEL
) 0x1234,
293 gBS
->FreePool (UpdateData
);
299 // Allocate space for creation of Buffer
301 Status
= gBS
->AllocatePool (
306 ASSERT_EFI_ERROR (Status
);
308 ZeroMem (UpdateData
, 0x1000);
311 // Initialize DataPacket with information intended to remove all
312 // previously created op-codes in the dynamic page
314 UpdateData
->FormSetUpdate
= FALSE
;
315 UpdateData
->FormCallbackHandle
= 0;
316 UpdateData
->FormUpdate
= FALSE
;
317 UpdateData
->FormTitle
= 0;
319 // Unlikely to be more than 0xff op-codes in the dynamic page to remove
321 UpdateData
->DataCount
= 0xff;
322 UpdateData
->Data
= NULL
;
325 // Remove all op-codes from dynamic page
327 Private
->Hii
->UpdateForm (
329 Private
->RegisteredHandle
,
330 (EFI_FORM_LABEL
) 0x1234, // Label 0x1234
331 FALSE
, // Remove Op-codes (will never remove form/endform)
332 UpdateData
// Significant value is UpdateData->DataCount
335 UpdateData
->FormSetUpdate
= FALSE
;
336 UpdateData
->FormCallbackHandle
= 0;
337 UpdateData
->FormUpdate
= FALSE
;
338 UpdateData
->FormTitle
= 0;
339 UpdateData
->DataCount
= 1;
343 STR_GOTO_FORM1
, // Token value for the Prompt
347 &UpdateData
->Data
// Buffer location to place op-codes
350 Private
->Hii
->UpdateForm (
352 Private
->RegisteredHandle
,
353 (EFI_FORM_LABEL
) 0x1234,
358 gBS
->FreePool (UpdateData
);
363 // If I hit the checkbox, I enter this case statement...
366 // Since I am returning an error (for test purposes) I need to pass in the string for the error
367 // I will allocate space for the return value. If an error occurs (which is the case) I can simply return
368 // an error and fill in the string parameter, otherwise, I will return information in the DataArray structure.
369 // The browser will free this packet structure
371 Status
= gBS
->AllocatePool (
373 sizeof (EFI_HII_CALLBACK_PACKET
) + sizeof (SAMPLE_STRING
) + 2,
376 ASSERT_EFI_ERROR (Status
);
378 ZeroMem (*Packet
, sizeof (EFI_HII_CALLBACK_PACKET
) + sizeof (SAMPLE_STRING
) + 2);
381 // Assign the buffer address to DataPacket
383 DataPacket
= *Packet
;
385 StrCpy (DataPacket
->String
, (CHAR16
*) SAMPLE_STRING
);
386 return EFI_DEVICE_ERROR
;
390 Status
= gBS
->AllocatePool (
392 sizeof (EFI_HII_CALLBACK_PACKET
) + 2,
395 ASSERT_EFI_ERROR (Status
);
397 ZeroMem (*Packet
, sizeof (EFI_HII_CALLBACK_PACKET
) + 2);
400 // Assign the buffer address to DataPacket
402 DataPacket
= *Packet
;
404 DataPacket
->DataArray
.EntryCount
= 1;
405 DataPacket
->DataArray
.NvRamMap
= NULL
;
406 ((EFI_IFR_DATA_ENTRY
*) (&DataPacket
->DataArray
+ 1))->Flags
= EXIT_REQUIRED
;
411 UnicodeSPrint (VariableName
, 0x80, (CHAR16
*) L
"%d", VAR_EQ_TEST_NAME
);
413 Status
= gRT
->SetVariable (
416 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
424 UnicodeSPrint (VariableName
, 0x80, (CHAR16
*) L
"%d", VAR_EQ_TEST_NAME
);
426 Status
= gRT
->SetVariable (
429 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
437 UnicodeSPrint (VariableName
, 0x80, (CHAR16
*) L
"%d", VAR_EQ_TEST_NAME
);
439 Status
= gRT
->SetVariable (
442 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
458 IN EFI_HANDLE ImageHandle
,
459 IN EFI_SYSTEM_TABLE
*SystemTable
463 EFI_HII_PROTOCOL
*Hii
;
465 // EFI_FORM_BROWSER_PROTOCOL *FormConfig;
467 EFI_HII_PACKAGES
*PackageList
;
468 EFI_HII_HANDLE HiiHandle
;
469 STRING_REF TokenToUpdate
;
470 STRING_REF TokenToUpdate2
;
471 STRING_REF TokenToUpdate3
;
473 EFI_HII_UPDATE_DATA
*UpdateData
;
474 EFI_CALLBACK_INFO
*CallbackInfo
;
476 EFI_SCREEN_DESCRIPTOR Screen
;
478 ZeroMem (&Screen
, sizeof (EFI_SCREEN_DESCRIPTOR
));
480 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &Screen
.RightColumn
, &Screen
.BottomRow
);
483 // Remove 3 characters from top and bottom
486 Screen
.BottomRow
= Screen
.BottomRow
- 3;
489 // There should only be one HII protocol
491 Status
= gBS
->LocateProtocol (
492 &gEfiHiiProtocolGuid
,
496 if (EFI_ERROR (Status
)) {
502 // There should only be one Form Configuration protocol
504 Status = gBS->LocateProtocol (
505 &gEfiFormBrowserProtocolGuid,
509 if (EFI_ERROR (Status)) {
513 Status
= gBS
->AllocatePool (
515 sizeof (EFI_CALLBACK_INFO
),
516 (VOID
**) &CallbackInfo
518 if (EFI_ERROR (Status
)) {
522 CallbackInfo
->Signature
= EFI_CALLBACK_INFO_SIGNATURE
;
523 CallbackInfo
->Hii
= Hii
;
526 // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator
528 CallbackInfo
->DriverCallback
.NvRead
= NULL
;
529 CallbackInfo
->DriverCallback
.NvWrite
= NULL
;
530 CallbackInfo
->DriverCallback
.Callback
= DriverCallback
;
533 // Install protocol interface
536 Status
= gBS
->InstallProtocolInterface (
538 &gEfiFormCallbackProtocolGuid
,
539 EFI_NATIVE_INTERFACE
,
540 &CallbackInfo
->DriverCallback
543 ASSERT_EFI_ERROR (Status
);
545 CallbackInfo
->CallbackHandle
= Handle
;
547 PackageList
= PreparePackages (1, &mStringPackGuid
, DriverSampleStrings
);
548 Status
= Hii
->NewPack (Hii
, PackageList
, &HiiHandle
);
549 gBS
->FreePool (PackageList
);
551 PackageList
= PreparePackages (1, &mStringPackGuid
, InventoryBin
);
552 Status
= Hii
->NewPack (Hii
, PackageList
, &HiiHandle
);
553 gBS
->FreePool (PackageList
);
555 PackageList
= PreparePackages (1, &mStringPackGuid
, VfrBin
);
556 Status
= Hii
->NewPack (Hii
, PackageList
, &HiiHandle
);
557 gBS
->FreePool (PackageList
);
559 CallbackInfo
->RegisteredHandle
= HiiHandle
;
562 // Very simple example of how one would update a string that is already
563 // in the HII database
565 TokenToUpdate
= (STRING_REF
) STR_CPU_STRING2
;
566 NewString
= (CHAR16
*) L
"700 Mhz";
568 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate
, NewString
);
571 // Add a string - if 0 will be updated with new Token number
573 TokenToUpdate
= (STRING_REF
) 0;
576 // Add a string - if 0 will be updated with new Token number
578 TokenToUpdate2
= (STRING_REF
) 0;
581 // Add a string - if 0 will be updated with new Token number
583 TokenToUpdate3
= (STRING_REF
) 0;
585 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate
, (CHAR16
*) L
"Desired Speed");
586 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate2
, (CHAR16
*) L
"5 Thz");
587 Hii
->NewString (Hii
, NULL
, HiiHandle
, &TokenToUpdate3
, (CHAR16
*) L
"This is next year's desired speed - right?");
590 // Allocate space for creation of Buffer
592 Status
= gBS
->AllocatePool (
595 (VOID
**) &UpdateData
597 ASSERT_EFI_ERROR (Status
);
599 ZeroMem (UpdateData
, 0x1000);
602 // Flag update pending in FormSet
604 UpdateData
->FormSetUpdate
= TRUE
;
606 // Register CallbackHandle data for FormSet
608 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) CallbackInfo
->CallbackHandle
;
609 UpdateData
->FormUpdate
= FALSE
;
610 UpdateData
->FormTitle
= 0;
611 UpdateData
->DataCount
= 1;
613 CreateTextOpCode (TokenToUpdate
, TokenToUpdate2
, TokenToUpdate3
, 0, 0, &UpdateData
->Data
);
615 Hii
->UpdateForm (Hii
, HiiHandle
, (EFI_FORM_LABEL
) 100, TRUE
, UpdateData
);
617 gBS
->FreePool (UpdateData
);
620 // Example of how to display only the item we sent to HII
622 if (DISPLAY_ONLY_MY_ITEM
== 0x0001) {
624 // Have the browser pull out our copy of the data, and only display our data
626 // Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL);
630 // Have the browser pull out all the data in the HII Database and display it.
632 // Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL);
636 if (EFI_ERROR (Status
)) {