# 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="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2F7BS1bpIHe0R2IQ2glU2V%2Fimage.png?alt=media&#x26;token=94591192-ad84-43b2-b5a6-f5cf3633eda4" 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="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FDwNjW2Lsjz2zWYoEzvCj%2Fimage.png?alt=media&#x26;token=3eb6430e-81d7-4c3b-88dd-12d2bc3845db" 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="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FzBac2a2kwyv1HuYxsD2R%2Fimage.png?alt=media&#x26;token=4108dc12-d54e-4e94-8914-6a7db794d991" 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="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2F6UD7DqKR7aJ4p85hrmKM%2Fimage.png?alt=media&#x26;token=83635c86-6f94-4540-8359-17a82db9d565" 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="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FfMlFHUYGNGugUu7zSZsk%2Fimage.png?alt=media&#x26;token=251b61cc-a887-47c7-af44-b2f59d38cd24" 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="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FAoYbHv382iNqsFL1euTv%2Fimage.png?alt=media&#x26;token=9b979865-dac0-48e3-bcc5-f181af9f2215" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>

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

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

<figure><img src="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FcWXJoWr1WWkwxo4C0jtY%2Fimage.png?alt=media&#x26;token=dcc37238-af05-4bc6-af82-ab7da2232c67" 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="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FWnStKjR3pd8PIZ8xdLGq%2Fimage.png?alt=media&#x26;token=75aaef32-5cb6-4fdf-ae09-4eeea3afcdc9" alt=""><figcaption><p>HIIStaticForm.efi</p></figcaption></figure>
