Let's start to investigate form elements.
Create new app HIIStaticForm
with a content similar to our HIISimpleForm
app. I won't repeat all the steps, as in this lesson we would only change form content.
So we start with this VFR:
#define HIISTATICFORM_FORMSET_GUID {0x32783cc5, 0xe551, 0x4b61, {0xb7, 0xbd, 0x41, 0xba, 0x71, 0x7f, 0xba, 0x81}}
formset
guid = HIISTATICFORM_FORMSET_GUID,
title = STRING_TOKEN(HIISTATICFORM_FORMSET_TITLE),
help = STRING_TOKEN(HIISTATICFORM_FORMSET_HELP),
form
formid = 1,
title = STRING_TOKEN(HIISTATICFORM_FORMID1_TITLE);
endform;
endformset;
And it produces the folowing code:
formset
>00000000: 0E A7 C5 3C 78 32 51 E5 61 4B B7 BD 41 BA 71 7F BA 81 02 00 03 00 01 71 99 03 93 45 85 04 4B B4 5E 32 EB 83 26 04 0E
>00000027: 5C 06 00 00 00 00
>0000002D: 5C 06 00 00 01 00
guid = {0x32783cc5, 0xe551, 0x4b61, {0xb7, 0xbd, 0x41, 0xba, 0x71, 0x7f, 0xba, 0x81}},
title = STRING_TOKEN(0x0002),
help = STRING_TOKEN(0x0003),
form
>00000033: 01 86 01 00 04 00
formid = 1,
title = STRING_TOKEN(0x0004);
endform;
>00000039: 29 02
endformset;
>0000003B: 29 02
And as you remember this creates an empty form with a title.
The most simple form element is subtitle (https://edk2-docs.gitbook.io/edk-ii-vfr-specification/2_vfr_description_in_bnf/211_vfr_form_definition#2.11.5.1-vfr-subtitle-definition). It is a non-interactive text to display some information to the user. Is is not possible to select this element. In EDKII form browser it is also displayed in a blue color (opposed to the interactive elements, that would be displayed in black color).
You can add subtitle with this code:
subtitle
text = STRING_TOKEN(SUBTITLE1),
endsubtitle;
But it is most common to use a short form:
subtitle text = STRING_TOKEN(SUBTITLE1);
Simply embed this string inside our form code:
...
form
formid = 1,
title = STRING_TOKEN(HIISTATICFORM_FORMID1_TITLE);
subtitle text = STRING_TOKEN(SUBTITLE1);
endform;
...
Off course you should declare this string in the UNI file:
#string SUBTITLE1 #language en-US "Subtitle1"
This VFR would produce following picture:
formset
>00000000: 0E A7 C5 3C 78 32 51 E5 61 4B B7 BD 41 BA 71 7F BA 81 02 00 03 00 01 71 99 03 93 45 85 04 4B B4 5E 32 EB 83 26 04 0E
>00000027: 5C 06 00 00 00 00
>0000002D: 5C 06 00 00 01 00
guid = {0x32783cc5, 0xe551, 0x4b61, {0xb7, 0xbd, 0x41, 0xba, 0x71, 0x7f, 0xba, 0x81}},
title = STRING_TOKEN(0x0002),
help = STRING_TOKEN(0x0003),
form
>00000033: 01 86 01 00 04 00
formid = 1,
title = STRING_TOKEN(0x0004);
subtitle text = STRING_TOKEN(0x0005);
>00000039: 02 87 05 00 00 00 00
>00000040: 29 02
endform;
>00000042: 29 02
endformset;
>00000044: 29 02
If you compare output before and after you could see that the difference is:
subtitle text = STRING_TOKEN(0x0005);
>00000039: 02 87 05 00 00 00 00
>00000040: 29 02
It is two opcodes: EFI_IFR_SUBTITLE
and our EFI_IFR_END
. We've already seen the structure for the EFI_IFR_END
, so let's look at the EFI_IFR_SUBTITLE
:
EFI_IFR_SUBTITLE
Summary:
Creates a sub-title in the current form.
Prototype:
#define EFI_IFR_SUBTITLE_OP 0x02
typedef struct _EFI_IFR_SUBTITLE {
EFI_IFR_OP_HEADER Header;
EFI_IFR_STATEMENT_HEADER Statement;
UINT8 Flags;
} EFI_IFR_SUBTITLE;
Members:
Header The sequence that defines the type of opcode as well as the length of the opcode being defined.
For this tag, Header.OpCode = EFI_IFR_SUBTITLE_OP.
Flags Identifies specific behavior for the sub-title.
If you add another subtitle similar to like we did it above:
...
form
formid = 1,
title = STRING_TOKEN(HIISTATICFORM_FORMID1_TITLE);
subtitle text = STRING_TOKEN(SUBTITLE1);
subtitle text = STRING_TOKEN(SUBTITLE2);
endform;
...
This subtitle will be simply printed on the next string. This principle is true for all form elements. Next element by default will simply go to another string.
As we saw above, EFI_IFR_SUBTITLE
opens a scope which is later closed by the EFI_IFR_END
.
It is possible to define elements inside subtitle scope which will indent all the elements inside the scope.
Add this construction to our form:
subtitle
text = STRING_TOKEN(SUBTITLE3),
subtitle text = STRING_TOKEN(SUBTITLE4);
endsubtitle;
If you look at the Form.lst
you would see that
subtitle
>0000004B: 02 87 07 00 00 00 00
text = STRING_TOKEN(0x0007),
subtitle text = STRING_TOKEN(0x0008);
>00000052: 02 87 08 00 00 00 00
>00000059: 29 02
endsubtitle;
>0000005B: 29 02
Here you can see opcodes EFI_IFR_SUBTITLE
-EFI_IFR_SUBTITLE
-EFI_IFR_END
-EFI_IFR_END
. If we didn't put SUBTITLE4
in the SUBTITLE3
scope, the output would be EFI_IFR_SUBTITLE
-EFI_IFR_END
-EFI_IFR_SUBTITLE
-EFI_IFR_END
.
To get more deeper understanding add another subtitle inside the scope of SUBTITLE3
and another after the scope:
subtitle
text = STRING_TOKEN(SUBTITLE3),
subtitle text = STRING_TOKEN(SUBTITLE4);
subtitle text = STRING_TOKEN(SUBTITLE5);
endsubtitle;
subtitle text = STRING_TOKEN(SUBTITLE6);
Subtitle element is an easy way to add an empty string to your form.
Insert this code right before the SUBTITLE6
definition
subtitle text = STRING_TOKEN(STR_NULL);
And define STR_NULL
as:
#string STR_NULL #language en-US ""
This would give you:
The next element that we will discuss is text
(https://edk2-docs.gitbook.io/edk-ii-vfr-specification/2_vfr_description_in_bnf/211_vfr_form_definition#2.11.5.2-vfr-text-definition). Add following code to our form right after the last subtitle:
text
help = STRING_TOKEN(TEXT1_help),
text = STRING_TOKEN(TEXT1_text);
If you would look at the Form.lst
, you'll see that text
doesn't open a scope, therefore only one IFR is produced - EFI_IFR_TEXT
:
text
>00000078: 03 08 0C 00 0D 00 00 00
help = STRING_TOKEN(0x000D),
text = STRING_TOKEN(0x000C);
EFI_IFR_TEXT
Summary:
Creates a static text and image.
Prototype:
#define EFI_IFR_TEXT_OP 0x03
typedef struct _EFI_IFR_TEXT {
EFI_IFR_OP_HEADER Header;
EFI_IFR_STATEMENT_HEADER Statement;
EFI_STRING_ID TextTwo;
} EFI_IFR_TEXT;
Members:
Header The sequence that defines the type of opcode as well as the length of the opcode being defined.
For this tag, Header.OpCode = EFI_IFR_TEXT_OP.
Statement Standard statement header.
TextTwo The string token reference to the secondary string for this opcode.
Description:
This is a static text/image statement.
And here is a definition for the EFI_IFR_STATEMENT_HEADER
field:
EFI_IFR_STATEMENT_HEADER
Summary:
Standard statement header.
Prototype:
typedef struct _EFI_IFR_STATEMENT_HEADER {
EFI_STRING_ID Prompt;
EFI_STRING_ID Help;
} EFI_IFR_STATEMENT_HEADER;
Members:
Prompt The string identifier of the prompt string for this particular statement. The value 0 indicates no prompt string.
Help The string identifier of the help string for this particular statement. The value 0 indicates no help string
Description:
This is the standard header for statements, including questions.
On the screen text
element looks like this:
The main difference of the text
element from the subtitle
element is that you can select text
elements.
This is more obvious if you'll add another text element right after the first one:
Now you can use arrow keys to select either Text1 title
or Text2 title
. And when you would do this help text for title would change automatically.
It is possible to add another text field to the text element:
text
help = STRING_TOKEN(TEXT3_HELP),
text = STRING_TOKEN(TEXT3_TEXT);
text = STRING_TOKEN(TEXT3_TEXT_TWO);
Its string would go to the EFI_IFR_TEXT.TextTwo
field.
In the browser it would like this. The second string is placed in a choice place for the menu item: