Skip to content

Latest commit

 

History

History

Lesson_58

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.

Subtitle

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:

Subtitle1

IFR

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.

Another subtitle

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.

Subtitle2

Utilizing subtitle scope

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.

Subtitle3

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);

Subtitle4

Empty string

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:

Subtitle5

Text element

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:

Text1

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:

Text2

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.

Another text field

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:

Text3