# 58. VFR 요소 : subtitle 및 text

이번 장에서는 폼 요소에 대해 알아본다.

이전 장에서 생성한 `HIISimpleForm` 애플리케이션과 비슷한 내용으로 새로운 `HIIStaticForm` 애플리케이션을 생성한다. 이전 장에서 생성한 애플리케이션과 차이는 폼 내용만 변경하므로 생성하는 방법은 다루지 않는다. `Strings.uni` 파일도 수정해야 한다.

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

빌드를 진행하면 아래와 같은 코드를 생성한다.\
`Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIStaticForm/HIIStaticForm/DEBUG/Form.lst`

```
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
```

이 형태는 제목이 있는 빈 형태로 생성된다.

### Subtitle

가장 간단한 폼 요소는 `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> \
사용자에게 일부 정보를 표시하기 위한 대화형이 아닌 텍스트이다. 이 요소는 선택할 수 없다. EDKII Form Browser에서는 검은색으로 표시되는 대화형 요소와는 반대로 파란색으로 표시된다.

아래 코드로 `subtitle`을 추가할 수 있다.

```
subtitle
  text = STRING_TOKEN(SUBTITLE1),
endsubtitle;
```

그러나 짧은 폼을 사용하는 것이 가장 일반적이다.

```
subtitle text = STRING_TOKEN(SUBTITLE1);
```

따라서 위 문자열을 폼 코드에 작성하면 된다.

```
...
form
  formid = 1,
  title = STRING_TOKEN(HIISTATICFORM_FORMID1_TITLE);

  subtitle text = STRING_TOKEN(SUBTITLE1);
endform;
...
```

UNI 파일에 `subtitle`을 위한 문자열을 추가한다.

```
#string SUBTITLE1                            #language en-US  "Subtitle1"
```

빌드 후 `HIIStaticForm.c`를 실행하면 아래와 같이 Subtitle1이 출력된 것을 볼 수 있다.

<figure><img src="/files/3U2JbvrzHh0fLz1CCp3c" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

### 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
```

`subtitle` 추가 이전과 이후의 출력을 비교하면 아래와 같이 차이가 있다.

```
    subtitle text = STRING_TOKEN(0x0005);
>00000039: 02 87 05 00 00 00 00
>00000040: 29 02
```

2개의 opcode `EFI_IFR_SUBTITLE`과 `EFI_IFR_END`가 있다. 이미 `EFI_IFR_END`의 구조를 확인했기 때문에 이번에는 `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.
```

### 다른 subtitle

위에서 했던 것과 비슷하게 `subtitle`을 하나 더 생성한다.

```
...
form
  formid = 1,
  title = STRING_TOKEN(HIISTATICFORM_FORMID1_TITLE);

  subtitle text = STRING_TOKEN(SUBTITLE1);
  subtitle text = STRING_TOKEN(SUBTITLE2);
endform;
...
```

이 `subtitle2`는 `subtitle1` 뒤에 출력된다. 이 원칙은 모든 폼 요소에 적용된다. 기본적으로 다음 요소는 단순히 다른 문자열로 이동한다.

<figure><img src="/files/kLeL868WjzufHY42IgO7" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

### subtitle 범위 활용

위에서 봤듯이 `EFI_IFR_SUBTITLE`은 나중에 `EFI_IFR_END`에 의해 닫힌 범위를 열 수 있다.

`subtitle` 범위 내의 요소를 정의하여 범위 내의 모든 요소를 들여 쓸 수 있다.

아래 내용을 `Form.vfr` 파일에 작성한다.

```
subtitle
  text = STRING_TOKEN(SUBTITLE3),

  subtitle text = STRING_TOKEN(SUBTITLE4);
endsubtitle;
```

`Strings.uni` 파일에도 `SUBTITLE3`과 `SUBTITLE4`를 추가한다.

```
#string SUBTITLE3                            #language en-US  "Subtitle3"
#string SUBTITLE4                            #language en-US  "Subtitle4"
```

빌드 후 `Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIStaticForm/HIIStaticForm/DEBUG/Form.lst` 내용을 살펴보면 아래와 같이 추가된 것을 볼 수 있다.

```
    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
```

opcode `EFI_IFR_SUBTITLE`-`EFI_IFR_SUBTITLE`-`EFI_IFR_END`-`EFI_IFR_END`를 확인할 수 있다. 만약 `SUBTITLE4`를 `SUBTITLE3` 범위에 넣지 않았을 경우에는 `EFI_IFR_SUBTITLE`-`EFI_IFR_END`-`EFI_IFR_SUBTITLE`-`EFI_IFR_END`로 된다.

<figure><img src="/files/Fn6upfW8JPvLagpjIYUq" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

더 깊게 이해하기 위해 `SUBTITLE3`의 범위 안에 다른 `subtitle`을 추가하고 범위 뒤에 다른 `subtitle`을 추가한다.

```
subtitle
  text = STRING_TOKEN(SUBTITLE3),

  subtitle text = STRING_TOKEN(SUBTITLE4);
  subtitle text = STRING_TOKEN(SUBTITLE5);
endsubtitle;

subtitle text = STRING_TOKEN(SUBTITLE6);
```

`Strings.uni`에도 `SUBTITLE5`와 `SUBTITLE6`을 추가한다.

```
#string SUBTITLE5                            #language en-US  "Subtitle5"
#string SUBTITLE6                            #language en-US  "Subtitle6"
```

<figure><img src="/files/R5UidbU3a4u6v2B6jRZC" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

### 빈 문자열

`subtitle` 요소는 빈 문자열을 폼에 쉽게 추가할 수 있는 방법이다.

`SUBTITLE6` 바로 위에 아래 코드를 작성한다.

```
subtitle text = STRING_TOKEN(STR_NULL);
```

`Strings.uni`에 `STR_NULL`을 추가한다.

```
#string STR_NULL                             #language en-US  ""
```

빌드 후 실행하면 `SUBTITLE6` 위가 띄어진 것을 볼 수 있다.

<figure><img src="/files/F2A0q174jpUk7qsOSXjT" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

### Text 요소

이번에 알아볼 요소는 `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>

`Form.vfr` 파일의 마지막 `subtitle` 아래에 코드를 작성한다.

```
text
  help = STRING_TOKEN(TEXT1_HELP),
  text = STRING_TOKEN(TEXT1_TEXT);
```

`Strings.uni` 파일에 추가한다.

```
#string TEXT1_TEXT                           #language en-US  "Text1 title"
#string TEXT1_HELP                           #language en-US  "Text1 help"
```

`Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIStaticForm/HIIStaticForm/DEBUG/Form.lst`를 확인하면 `text`가 범위를 열지 않아 하나의 `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.
```

아래는 `EFI_IFR_STATEMENT_HEADER` 필드에 대한 정의다.

```
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.
```

`text` 요소는 아래와 같이 출력된다.

<figure><img src="/files/Ox5Idiagj2EChiBBW8pv" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

`text` 요소와 `subtitle` 요소의 차이점은 `text` 요소는 선택할 수 있다는 점이다.

TEXT1 title을 생성했던 방법과 똑같이 TEXT2 title을 생성한다.

<figure><img src="/files/uJn5cGSWbG2LkexZ21MO" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

방향키를 사용해 `Text1 title`과 `Text2 title`을 선택할 수 있고 선택된 `text`에 따라 `help`도 자동으로 변경된다.

### 다른 text 필드

`text` 필드에 다른 `text` 요소를 추가할 수 있다.

```
text
  help = STRING_TOKEN(TEXT3_HELP),
  text = STRING_TOKEN(TEXT3_TEXT),
  text = STRING_TOKEN(TEXT3_TEXT_TWO);
```

```
#string TEXT3_TEXT                           #language en-US  "Text3 title"
#string TEXT3_TEXT_TWO                       #language en-US  "Text3 value"
#string TEXT3_HELP                           #language en-US  "Text3 help"
```

추가된 `text` 요소는 `EFI_IFR_TEXT.TextTwo` 필드에 추가된다.

Form Browser에는 아래와 같이 출력된다. 두 번째 문자열은 메뉴 항목의 선택된 위치에 배치된다.

<figure><img src="/files/1ngOFBHtcQ4iVXOqUjt5" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bob-mcd-team.gitbook.io/uefi/uefi-development/vfr/58.subtitle-and-text.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
