# 66. VFR 추가 입력 요소 Part 2: string

이번 장에서는 다른 데이터 입력 VFR 요소를 살펴보겠다. - `string` <https://edk2-docs.gitbook.io/edk-ii-vfr-specification/2_vfr_description_in_bnf/211_vfr_form_definition#2.11.6.7.1-vfr-string-statement-definition>

해당 요소는 `CHAR16` 문자열을 저장하기 위해 사용된다.\
이전과 동일하게 `minsize`/`maxsize` 요소는 문자열에 필수로 사용되며 아래는 VFR 코드에 추가해야 하는 최소한의 코드이다.

```
string
  varid = FormData.StringValue,
  prompt = STRING_TOKEN(STRING_PROMPT),
  help = STRING_TOKEN(STRING_HELP),
  minsize = 5,
  maxsize = 10,
endstring;
```

당연히 Strings.uni 파일에도 새로운 토큰을 추가해야 한다.

```
#string STRING_PROMPT          #language en-US  "String prompt"
#string STRING_HELP            #language en-US  "String help"
```

`UEFI_VARIABLE_STRUCTURE`의 경우 크기가 최소 `maxsize`인 `UINT16` 요소의 배열을 추가해야 한다.

```
typedef struct {
  UINT8 CheckboxValue;
  UINT16 NumericValue;
  UINT16 StringValue[10];
} UEFI_VARIABLE_STRUCTURE;
```

배열의 크기가 `maxsize`보다 작은 경우 EDKII 빌드 시스템에서 오류를 반환한다.

```
ERROR 12288: String MaxSize can't be larger than the max number of elements in string array.
```

이전과 동일하게 업데이트된 드라이버를 로드하기 전에 이전 UEFI 변수를 삭제해야 한다.

```
Shell> dmpstore -guid 531bc507-9191-4fa2-9446-b844e35dd12a -d
Delete variable '531BC507-9191-4FA2-9446-B844E35DD12A:FormData': Success
Shell> load fs0:HIIFormDataElements.efi
```

실행을 하면 아래와 같은 화면을 볼 수 있다.

<figure><img src="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FBNj3sxY7Y4QKHjDvoDkK%2Fimage.png?alt=media&#x26;token=0612e3b2-ad96-4556-abe5-d6787102155a" alt=""><figcaption></figcaption></figure>

`minsize`를 5로 정의했기 때문에 5미만의 문자열 입력이 불가능하다.

<figure><img src="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FE82srMgWw5guOFfBqjnh%2Fimage.png?alt=media&#x26;token=c8840669-8385-4c03-bf62-68203a26b68f" alt=""><figcaption></figcaption></figure>

또한 maxsize는 10으로 정의했기 때문에 10이상의 문자열을 입력 불가능하다. 이외에도 HII는 기호를 입력하는 것에도 제한을 한다.

<figure><img src="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FGJVOd0v8neMDIDJN8pEt%2Fimage.png?alt=media&#x26;token=d52af05a-d993-4830-9ca1-c9b1b999ff5e" alt=""><figcaption></figcaption></figure>

이 모든 것을 고려해서 작성하면 성공적으로 데이터가 저장되는 것을 볼 수 있다.

<figure><img src="https://224378457-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgAFiQ5sYs9AjXHJxMFpe%2Fuploads%2FUFy6rsCDaHQygauYYo1U%2Fimage.png?alt=media&#x26;token=3fc4e740-106e-47a1-bb54-1de7419a29aa" alt=""><figcaption></figcaption></figure>

이후 UEFI 변수를 확인하면 값이 저장된 것을 확인 가능하다.

```
Shell> dmpstore -guid 531bc507-9191-4fa2-9446-b844e35dd12a
Variable NV+BS '531BC507-9191-4FA2-9446-B844E35DD12A:FormData' DataSize = 0x17
  00000000: 00 00 00 55 00 45 00 46-00 49 00 2D 00 4C 00 65  *...U.E.F.I.-.L.e*
  00000010: 00 73 00 73 00 6F 00                             *.s.s.o.*
```

위의 값에서 보다시피 문자열에는 `\0` 종료 기호가 포함되어 있지 않다. 따라서 단순하게 배열 크기를 VFR `maxsize` 필드의 값보다 하나 크게 선언하는 것이 나을 수 있다\
(예: `CHAR16 StringValue[11]`).

이렇게 하면 UEFI 변수에서 문자열 필드를 더 쉽게 파싱할 수 있다.

```
Shell> dmpstore -guid 531bc507-9191-4fa2-9446-b844e35dd12a
Variable NV+BS '531BC507-9191-4FA2-9446-B844E35DD12A:FormData' DataSize = 0x19
  00000000: 00 00 00 55 00 45 00 46-00 49 00 2D 00 4C 00 65  *...U.E.F.I.-.L.e*
  00000010: 00 73 00 73 00 6F 00 00-00                       *.s.s.o...*
```

## MULTI\_LINE

VFR 사양은 `string` 요소에 대한 `MULTI_LINE` 플래그를 정의한다.

```
string
  varid = FormData.StringValue,
  prompt = STRING_TOKEN(STRING_PROMPT),
  help = STRING_TOKEN(STRING_HELP),
  flags = MULTI_LINE,
  minsize = 5,
  maxsize = 10,
endstring;
```

이 플래그는 여러 줄의 텍스트가 허용될 수 있는 양식 브라우저에 대한 힌트로 작동해야 한다. 그러나 현재 OVMF 양식 브라우저는 해당 플래그를 사용하지 않는다.

## IFR

`Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements/DEBUG/Form.lst`에  존재하는 IFR 코드를 확인하자.

```
    string
>00000082: 1C 90 09 00 0A 00 03 00 01 00 03 00 00 05 0A 00
      varid = FormData.StringValue,
      prompt = STRING_TOKEN(0x0009),
      help = STRING_TOKEN(0x000A),
      minsize = 5,
      maxsize = 10,
    endstring;
>00000092: 29 02
```

해당 데이터는 `EFI_IFR_STRING` 구조체를 인코딩 한 것이다.

```
Summary:
Defines the string question.

Prototype:
#define EFI_IFR_STRING_OP 0x1C

typedef struct _EFI_IFR_STRING {
 EFI_IFR_OP_HEADER Header;
 EFI_IFR_QUESTION_HEADER Question;
 UINT8 MinSize;
 UINT8 MaxSize;
 UINT8 Flags;
} EFI_IFR_STRING;

Members:
Header 		The sequence that defines the type of opcode as well as the length of the opcode being defined.
		Header.OpCode = EFI_IFR_STRING_OP.
Question 	The standard question header.
MinSize 	The minimum number of characters that can be accepted for this opcode.
MaxSize 	The maximum number of characters that can be accepted for this opcode.
Flags 		Flags which control the string editing behavior.

Description:
This creates a string question. The minimum length is MinSize and the maximum length is MaxSize
```

데이터를 파싱할 수 있지만 실제로 새롭게 얻을 수 있는 것은 없다.

## Note

해당 글을 쓰는 시점에서 EDKII 빌드 시스템을 속이고 크기가 10이지만 유형이 UINT8인 StringValue 배열을 선언할 수 있다. 해당 코드는 컴파일되지만 모든 것이 잘 될 수 있다고 기대해서는 안된다. 바로 지금 이렇게 속인 것으로 인하여 HII 시스템은 양식을 저장할 수 있게 되고 아무 에러도 나타나지 않는 것이다. 그러나 실제 값 데이터는 여전히 폼 데이터와 동일하지 않기 때문에 HII는 폼 데이터를 무한정으로 저장하도록 할 수 있다.


---

# 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/66.vfr-string.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.
