diff options
Diffstat (limited to 'Lessons')
-rw-r--r-- | Lessons/Lesson_68/OneOf1.png | bin | 0 -> 6361 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/OneOf2.png | bin | 0 -> 7026 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/OneOf3.png | bin | 0 -> 6359 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/Orderedlist1.png | bin | 0 -> 7874 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/Orderedlist2.png | bin | 0 -> 7833 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/Orderedlist3.png | bin | 0 -> 7772 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/Orderedlist4.png | bin | 0 -> 7896 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/Orderedlist5.png | bin | 0 -> 7435 bytes | |||
-rw-r--r-- | Lessons/Lesson_68/README.md | 370 | ||||
-rw-r--r-- | Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Data.h | 20 | ||||
-rw-r--r-- | Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Form.vfr | 72 | ||||
-rw-r--r-- | Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.c | 140 | ||||
-rw-r--r-- | Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.inf | 22 | ||||
-rw-r--r-- | Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Strings.uni | 31 |
14 files changed, 655 insertions, 0 deletions
diff --git a/Lessons/Lesson_68/OneOf1.png b/Lessons/Lesson_68/OneOf1.png Binary files differnew file mode 100644 index 0000000..2ad8398 --- /dev/null +++ b/Lessons/Lesson_68/OneOf1.png diff --git a/Lessons/Lesson_68/OneOf2.png b/Lessons/Lesson_68/OneOf2.png Binary files differnew file mode 100644 index 0000000..acc0a7a --- /dev/null +++ b/Lessons/Lesson_68/OneOf2.png diff --git a/Lessons/Lesson_68/OneOf3.png b/Lessons/Lesson_68/OneOf3.png Binary files differnew file mode 100644 index 0000000..5ca7322 --- /dev/null +++ b/Lessons/Lesson_68/OneOf3.png diff --git a/Lessons/Lesson_68/Orderedlist1.png b/Lessons/Lesson_68/Orderedlist1.png Binary files differnew file mode 100644 index 0000000..37520ca --- /dev/null +++ b/Lessons/Lesson_68/Orderedlist1.png diff --git a/Lessons/Lesson_68/Orderedlist2.png b/Lessons/Lesson_68/Orderedlist2.png Binary files differnew file mode 100644 index 0000000..a1df76a --- /dev/null +++ b/Lessons/Lesson_68/Orderedlist2.png diff --git a/Lessons/Lesson_68/Orderedlist3.png b/Lessons/Lesson_68/Orderedlist3.png Binary files differnew file mode 100644 index 0000000..8400673 --- /dev/null +++ b/Lessons/Lesson_68/Orderedlist3.png diff --git a/Lessons/Lesson_68/Orderedlist4.png b/Lessons/Lesson_68/Orderedlist4.png Binary files differnew file mode 100644 index 0000000..a4f6d4b --- /dev/null +++ b/Lessons/Lesson_68/Orderedlist4.png diff --git a/Lessons/Lesson_68/Orderedlist5.png b/Lessons/Lesson_68/Orderedlist5.png Binary files differnew file mode 100644 index 0000000..22d6527 --- /dev/null +++ b/Lessons/Lesson_68/Orderedlist5.png diff --git a/Lessons/Lesson_68/README.md b/Lessons/Lesson_68/README.md new file mode 100644 index 0000000..cdd606f --- /dev/null +++ b/Lessons/Lesson_68/README.md @@ -0,0 +1,370 @@ +# `oneof` element + +`oneof` element allows to select on option from the predefined set (https://edk2-docs.gitbook.io/edk-ii-vfr-specification/2_vfr_description_in_bnf/211_vfr_form_definition#2.11.6.6.2-vfr-oneof-statement-definition) + +Add the folowing code to the `UefiLessonsPkg/HIIFormDataElements/Form.vfr` +``` +oneof + varid = FormData.OneOfValue, + prompt = STRING_TOKEN(ONEOF_PROMPT), + help = STRING_TOKEN(ONEOF_HELP), + option text = STRING_TOKEN(ONEOF_OPTION1), value = 0x00, flags = DEFAULT; + option text = STRING_TOKEN(ONEOF_OPTION2), value = 0x33, flags = 0; + option text = STRING_TOKEN(ONEOF_OPTION3), value = 0x55, flags = 0; +endoneof; +``` + +Add new string tokens to the `UefiLessonsPkg/HIIFormDataElements/Strings.uni`: +``` +#string ONEOF_PROMPT #language en-US "OneOf list prompt" +#string ONEOF_HELP #language en-US "OneOf list help" +#string ONEOF_OPTION1 #language en-US "OneOf list option 1" +#string ONEOF_OPTION2 #language en-US "OneOf list option 2" +#string ONEOF_OPTION3 #language en-US "OneOf list option 3" +``` + +As for data, add this to the `UefiLessonsPkg/HIIFormDataElements/Data.h`: +``` +typedef struct { + ... + UINT8 OneOf; +} UEFI_VARIABLE_STRUCTURE; +``` + +Once you load the form, you get: + +![OneOf1](OneOf1.png?raw=true "OneOf1") + +You can select one of the available options: + +![OneOf2](OneOf2.png?raw=true "OneOf2") + +If you select the option 2: + +![OneOf3](OneOf3.png?raw=true "OneOf3") + +The variable field would get the value `0x33`. If you want to, you can verify it with `dmpstore`. + +## IFR + +IFR code would look like this (Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements/DEBUG/Form.lst): +``` + oneof +>000000B4: 05 91 0F 00 10 00 06 00 01 00 20 00 00 10 00 55 00 + varid = FormData.OneOfValue, + prompt = STRING_TOKEN(0x000F), + help = STRING_TOKEN(0x0010), + option text = STRING_TOKEN(0x0011), value = 0x00, flags = DEFAULT; +>000000C5: 09 07 11 00 10 00 00 + option text = STRING_TOKEN(0x0012), value = 0x33, flags = 0; +>000000CC: 09 07 12 00 00 00 33 + option text = STRING_TOKEN(0x0013), value = 0x55, flags = 0; +>000000D3: 09 07 13 00 00 00 55 + endoneof; +>000000DA: 29 02 +``` + +The first opcodes are: +``` +EFI_IFR_ONE_OF + +Summary: +Creates a select-one-of question. + +Prototype: + +#define EFI_IFR_ONE_OF_OP 0x05 + +typedef struct _EFI_IFR_ONE_OF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + union { + struct { + UINT8 MinValue; + UINT8 MaxValue; + UINT8 Step; + } u8; + struct { + UINT16 MinValue; + UINT16 MaxValue; + UINT16 Step; + } u16; + struct { + UINT32 MinValue; + UINT32 MaxValue; + UINT32 Step; + } u32; + struct { + UINT64 MinValue; + UINT64 MaxValue; + UINT64 Step; + } u64; + } data; +} EFI_IFR_ONE_OF; + +Members: +Header The sequence that defines the type of opcode as well as the length of the opcode being defined. + Header.OpCode = EFI_IFR_ONE_OF_OP. +Question The standard question header. +Flags Specifies flags related to the numeric question. +MinValue The minimum value to be accepted by the browser for this opcode. + The size of the data field may vary from 8 to 64 bits, depending on the size specified in Flags +MaxValue The maximum value to be accepted by the browser for this opcode. + The size of the data field may vary from 8 to 64 bits, depending on the size specified in Flags +Step Defines the amount to increment or decrement the value each time a user requests a value change. + If the step value is 0, then the input mechanism for the numeric value is to be free-form + and require the user to type in the actual value. + The size of the data field may vary from 8 to 64 bits, depending on the size specified in Flags + +Description: +This opcode creates a select-on-of object, where the user must select from one of the nested options. +This is identical to EFI_IFR_NUMERIC. +``` + +And here is a definition for the options opcodes: +``` +EFI_IFR_ONE_OF_OPTION + +Summary: +Creates a pre-defined option for a question. + +Prototype: + +#define EFI_IFR_ONE_OF_OPTION_OP 0x09 + +typedef struct _EFI_IFR_ONE_OF_OPTION { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Option; + UINT8 Flags; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_ONE_OF_OPTION; + +Members: +Header The sequence that defines the type of opcode as well as the length of the opcode being defined. + Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP. +Option The string token reference to the option description string for this particular opcode. +Flags Specifies the flags associated with the current option (EFI_IFR_OPTION_x) +Type Specifies the type of the option’s value (See EFI_IFR_TYPE) +Value The union of all of the different possible values. The actual contents (and size) + of the field depends on Type. +``` + +Description says that the content of the `Value` field is dependent on the value of the `Type` field. Here are all possible value types with comments of their type flags: +``` +typedef union { + UINT8 u8; // EFI_IFR_TYPE_NUM_SIZE_8 + UINT16 u16; // EFI_IFR_TYPE_NUM_SIZE_16 + UINT32 u32; // EFI_IFR_TYPE_NUM_SIZE_32 + UINT64 u64; // EFI_IFR_TYPE_NUM_SIZE_64 + BOOLEAN b; // EFI_IFR_TYPE_BOOLEAN + EFI_HII_TIME time; // EFI_IFR_TYPE_TIME + EFI_HII_DATE date; // EFI_IFR_TYPE_DATE + EFI_STRING_ID string; // EFI_IFR_TYPE_STRING, EFI_IFR_TYPE_ACTION + EFI_HII_REF ref; // EFI_IFR_TYPE_REF + // UINT8 buffer[]; // EFI_IFR_TYPE_BUFFER +} EFI_IFR_TYPE_VALUE; +``` + +And here are the actual values for the `EFI_IFR_TYPE_x` defines: +``` +#define EFI_IFR_TYPE_NUM_SIZE_8 0x00 +#define EFI_IFR_TYPE_NUM_SIZE_16 0x01 +#define EFI_IFR_TYPE_NUM_SIZE_32 0x02 +#define EFI_IFR_TYPE_NUM_SIZE_64 0x03 +#define EFI_IFR_TYPE_BOOLEAN 0x04 +#define EFI_IFR_TYPE_TIME 0x05 +#define EFI_IFR_TYPE_DATE 0x06 +#define EFI_IFR_TYPE_STRING 0x07 +#define EFI_IFR_TYPE_OTHER 0x08 +#define EFI_IFR_TYPE_UNDEFINED 0x09 +#define EFI_IFR_TYPE_ACTION 0x0A +#define EFI_IFR_TYPE_BUFFER 0x0B +#define EFI_IFR_TYPE_REF 0x0C +``` + +In our structure we've declared data as `UINT8 OneOf`. Therefore compiler automatically have deducted our type flag as `EFI_IFR_TYPE_NUM_SIZE_8`. If we change that to `UINT16 OneOf`, compiler would change the type field value to the `EFI_IFR_TYPE_NUM_SIZE_16`. + +Compare this output with the one that we had before: +``` + oneof +>000000B4: 05 94 0F 00 10 00 06 00 01 00 20 00 00 11 00 00 55 00 00 00 + varid = FormData.OneOfValue, + prompt = STRING_TOKEN(0x000F), + help = STRING_TOKEN(0x0010), + option text = STRING_TOKEN(0x0011), value = 0x00, flags = DEFAULT; +>000000C8: 09 08 11 00 11 01 00 00 + option text = STRING_TOKEN(0x0012), value = 0x33, flags = 0; +>000000D0: 09 08 12 00 01 01 33 00 + option text = STRING_TOKEN(0x0013), value = 0x55, flags = 0; +>000000D8: 09 08 13 00 01 01 55 00 + endoneof; +>000000E0: 29 02 +``` + +Although `EFI_IFR_TYPE_VALUE` can take many values besides numeric if you try to set its type to the `EFI_HII_DATE OneOfValue` for example, you would get an error: +``` +ERROR 12288: OneOf question only support UINT8, UINT16, UINT32 and UINT64 data type +``` + +So only subtype of `EFI_IFR_TYPE_VALUE` is supported. + +# `orderedlist` element + +Another element with options is the `orderedlist` element (https://edk2-docs.gitbook.io/edk-ii-vfr-specification/2_vfr_description_in_bnf/211_vfr_form_definition#2.11.6.8-vfr-orderedlist-statement-definition) + +Add this to the `UefiLessonsPkg/HIIFormDataElements/Form.vfr`: +``` +orderedlist + varid = FormData.OrderedListValue, + prompt = STRING_TOKEN(ORDERED_LIST_PROMPT), + help = STRING_TOKEN(ORDERED_LIST_HELP), + option text = STRING_TOKEN(ORDERED_LIST_OPTION1), value = 0x0A, flags = 0; + option text = STRING_TOKEN(ORDERED_LIST_OPTION2), value = 0x0B, flags = 0; + option text = STRING_TOKEN(ORDERED_LIST_OPTION3), value = 0x0C, flags = 0; +endlist; +``` + +Add strings to the `UefiLessonsPkg/HIIFormDataElements/Strings.uni`: +``` +#string ORDERED_LIST_PROMPT #language en-US "Ordered list prompt" +#string ORDERED_LIST_HELP #language en-US "Ordered list help" +#string ORDERED_LIST_OPTION1 #language en-US "Ordered list option 1" +#string ORDERED_LIST_OPTION2 #language en-US "Ordered list option 2" +#string ORDERED_LIST_OPTION3 #language en-US "Ordered list option 3" +``` + +If we have 3 options, we need to declare array of 3 elements. Let's declare them as `UINT8`: +``` +typedef struct { + ... + UINT8 OrderedListValue[3]; +} UEFI_VARIABLE_STRUCTURE; +``` + +On load form looks like this: + +![Orderedlist1](OrderedList1.png?raw=true "OrderedList1") + +If you select the element: + +![Orderedlist2](OrderedList2.png?raw=true "OrderedList2") + +You can change order by selecting an option and moving it up or down with the help of `+` and `-` keys: + +![Orderedlist3](OrderedList3.png?raw=true "OrderedList3") + +Change order to `2 1 3` and save it with `F10`: + +![Orderedlist4](OrderedList4.png?raw=true "OrderedList4") + +This would get the following data in the `OrderedListValue` field of our UEFI variable: +``` +0B 0A 0C +``` + +## IFR + +Let's look at the IFR code: `Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements/DEBUG/Form.lst`: +``` + orderedlist +>000000DC: 23 8F 14 00 15 00 07 00 01 00 21 00 00 03 00 + varid = FormData.OrderedListValue, + prompt = STRING_TOKEN(0x0014), + help = STRING_TOKEN(0x0015), + option text = STRING_TOKEN(0x0016), value = 0x0A, flags = 0; +>000000EB: 09 07 16 00 00 00 0A + option text = STRING_TOKEN(0x0017), value = 0x0B, flags = 0; +>000000F2: 09 07 17 00 00 00 0B + option text = STRING_TOKEN(0x0018), value = 0x0C, flags = 0; +>000000F9: 09 07 18 00 00 00 0C + endlist; +>00000100: 29 02 +``` + +First element if `EFI_IFR_ORDERED_LIST`: +``` +EFI_IFR_ORDERED_LIST + +Summary: +Creates a set question using an ordered list. + +#define EFI_IFR_ORDERED_LIST_OP 0x23 + +typedef struct _EFI_IFR_ORDERED_LIST { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MaxContainers; + UINT8 Flags; +} EFI_IFR_ORDERED_LIST; + +Members: +Header The byte sequence that defines the type of opcode as well as the length of the opcode being defined. + Header.OpCode = EFI_IFR_ORDERED_LIST_OP. +Question The standard question header. +MaxContainers The maximum number of entries for which this tag will maintain an order. + This value also identifies the size of the storage associated with this tag’s ordering array. +Flags A bit-mask that determines which unique settings are active for this opcode. + +Description: +Create an ordered list question in the current form. One thing to note is that valid values for the options +in ordered lists should never be a 0. +``` + +If you match data to the fields, you would get the following data for the new fields: +``` +UINT8 MaxContainers; // 0x03 +UINT8 Flags; // 0x00 +``` + +Everything is in order, our element has 3 options, and therefore `MaxContainers=0x03`. + +If you look at the options IFR code you could see that the options are encoded with the same opcode `EFI_IFR_ONE_OF_OPTION` that was used in `oneof` element. + +Therefore the principle is the same. If you encode our data as `UINT16` instead of `UINT8` +``` +UINT16 OrderedListValue[3]; +``` +The compiler would encode options as `EFI_IFR_TYPE_NUM_SIZE_16` (=`UINT16`) and in the storage they would look as: +``` +0B 00 0A 00 0C 00 +``` + +With the `orderedlist` it is even possible to use non-numeric data types. For example you can encode variable as array of dates: +``` +EFI_HII_DATE OrderedListValue[3]; +``` + +Change the code in VFR: +``` +orderedlist + varid = FormData.OrderedListValue, + prompt = STRING_TOKEN(ORDERED_LIST_PROMPT), + help = STRING_TOKEN(ORDERED_LIST_HELP), + option text = STRING_TOKEN(ORDERED_LIST_OPTION1), value = 2021/7/4, flags = 0; + option text = STRING_TOKEN(ORDERED_LIST_OPTION2), value = 2022/8/5, flags = 0; + option text = STRING_TOKEN(ORDERED_LIST_OPTION3), value = 2023/9/6, flags = 0; +endlist; +``` + +If you parse IFR data now, you could see that every option is encoded with `#define EFI_IFR_TYPE_DATE 0x06` type: +``` + orderedlist +>000000DC: 23 8F 14 00 15 00 07 00 01 00 21 00 00 0C 00 + varid = FormData.OrderedListValue, + prompt = STRING_TOKEN(0x0014), + help = STRING_TOKEN(0x0015), + option text = STRING_TOKEN(0x0016), value = 2021/7/4, flags = 0; +>000000EB: 09 0A 16 00 06 06 E5 07 07 04 + option text = STRING_TOKEN(0x0017), value = 2022/8/5, flags = 0; +>000000F5: 09 0A 17 00 06 06 E6 07 08 05 + option text = STRING_TOKEN(0x0018), value = 2023/9/6, flags = 0; +>000000FF: 09 0A 18 00 06 06 E7 07 09 06 + endlist; +>00000109: 29 02 +``` + +If the data array has a size lower than amount of available option, everything would compile, but in the HII, you would see only the first `array size` options. For example `UINT8 OrderedListValue[2]` would result to: + +![Orderedlistr5](OrderedList5.png?raw=true "OrderedList5") diff --git a/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Data.h b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Data.h new file mode 100644 index 0000000..ad5689a --- /dev/null +++ b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Data.h @@ -0,0 +1,20 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0x531bc507, 0x9191, 0x4fa2, {0x94, 0x46, 0xb8, 0x44, 0xe3, 0x5d, 0xd1, 0x2a}} + +#define UEFI_VARIABLE_STRUCTURE_NAME L"FormData" + +#pragma pack(1) +typedef struct { + UINT8 CheckboxValue; + UINT16 NumericValue; + CHAR16 StringValue[11]; + EFI_HII_DATE DateValue; + EFI_HII_TIME TimeValue; + UINT8 OneOfValue; + UINT8 OrderedListValue[3]; +} UEFI_VARIABLE_STRUCTURE; +#pragma pack() + +#endif diff --git a/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Form.vfr b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Form.vfr new file mode 100644 index 0000000..cd275a6 --- /dev/null +++ b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Form.vfr @@ -0,0 +1,72 @@ +#include <Uefi/UefiMultiPhase.h> +#include "Data.h" + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(FORMSET_TITLE), + help = STRING_TOKEN(FORMSET_HELP), + + efivarstore UEFI_VARIABLE_STRUCTURE, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = FormData, + guid = FORMSET_GUID; + + form + formid = 1, + title = STRING_TOKEN(FORMID1_TITLE); + + checkbox + varid = FormData.CheckboxValue, + prompt = STRING_TOKEN(CHECKBOX_PROMPT), + help = STRING_TOKEN(CHECKBOX_HELP), + endcheckbox; + + numeric + varid = FormData.NumericValue, + prompt = STRING_TOKEN(NUMERIC_PROMPT), + help = STRING_TOKEN(NUMERIC_HELP), + flags = NUMERIC_SIZE_2 | DISPLAY_UINT_HEX, + minimum = 0x1234, + maximum = 0xaa55, + step = 2, + endnumeric; + + string + varid = FormData.StringValue, + prompt = STRING_TOKEN(STRING_PROMPT), + help = STRING_TOKEN(STRING_HELP), + minsize = 5, + maxsize = 10, + endstring; + + date + varid = FormData.DateValue, + prompt = STRING_TOKEN(DATE_PROMPT), + help = STRING_TOKEN(DATE_HELP), + enddate; + + time + varid = FormData.TimeValue, + prompt = STRING_TOKEN(TIME_PROMPT), + help = STRING_TOKEN(TIME_HELP), + endtime; + + oneof + varid = FormData.OneOfValue, + prompt = STRING_TOKEN(ONEOF_PROMPT), + help = STRING_TOKEN(ONEOF_HELP), + option text = STRING_TOKEN(ONEOF_OPTION1), value = 0x00, flags = DEFAULT; + option text = STRING_TOKEN(ONEOF_OPTION2), value = 0x33, flags = 0; + option text = STRING_TOKEN(ONEOF_OPTION3), value = 0x55, flags = 0; + endoneof; + + orderedlist + varid = FormData.OrderedListValue, + prompt = STRING_TOKEN(ORDERED_LIST_PROMPT), + help = STRING_TOKEN(ORDERED_LIST_HELP), + option text = STRING_TOKEN(ORDERED_LIST_OPTION1), value = 0x0A, flags = 0; + option text = STRING_TOKEN(ORDERED_LIST_OPTION2), value = 0x0B, flags = 0; + option text = STRING_TOKEN(ORDERED_LIST_OPTION3), value = 0x0C, flags = 0; + endlist; + endform; +endformset; diff --git a/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.c b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.c new file mode 100644 index 0000000..5920b58 --- /dev/null +++ b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.c @@ -0,0 +1,140 @@ +#include <Library/BaseMemoryLib.h> +#include <Library/DevicePathLib.h> +#include <Library/HiiLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/UefiLib.h> +#include "Data.h" + +extern UINT8 FormBin[]; + +#pragma pack(1) +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; +#pragma pack() + +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +EFI_HII_HANDLE mHiiHandle = NULL; +EFI_HANDLE mDriverHandle = NULL; +EFI_STRING UEFIVariableName = UEFI_VARIABLE_STRUCTURE_NAME; + + +EFI_STATUS +EFIAPI +HIIFormDataElementsUnload ( + EFI_HANDLE ImageHandle + ) +{ + if (mHiiHandle != NULL) + HiiRemovePackages(mHiiHandle); + + EFI_STATUS Status; + UINTN BufferSize; + UEFI_VARIABLE_STRUCTURE EfiVarstore; + + BufferSize = sizeof(UEFI_VARIABLE_STRUCTURE); + Status = gRT->GetVariable( + UEFIVariableName, + &mHiiVendorDevicePath.VendorDevicePath.Guid, + NULL, + &BufferSize, + &EfiVarstore); + if (!EFI_ERROR(Status)) { + Status = gRT->SetVariable( + UEFIVariableName, + &mHiiVendorDevicePath.VendorDevicePath.Guid, + 0, + 0, + NULL); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't delete variable! %r\n", Status); + } + } + + Status = gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + NULL + ); + + return Status; +} + +EFI_STATUS +EFIAPI +HIIFormDataElementsEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + Status = gBS->InstallMultipleProtocolInterfaces( + &mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + UINTN BufferSize; + UEFI_VARIABLE_STRUCTURE EfiVarstore; + BufferSize = sizeof(UEFI_VARIABLE_STRUCTURE); + Status = gRT->GetVariable ( + UEFIVariableName, + &mHiiVendorDevicePath.VendorDevicePath.Guid, + NULL, + &BufferSize, + &EfiVarstore); + if (EFI_ERROR(Status)) { + ZeroMem(&EfiVarstore, sizeof(EfiVarstore)); + Status = gRT->SetVariable( + UEFIVariableName, + &mHiiVendorDevicePath.VendorDevicePath.Guid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(EfiVarstore), + &EfiVarstore); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't create variable! %r\n", Status); + } + } + + mHiiHandle = HiiAddPackages( + &gEfiCallerIdGuid, + mDriverHandle, + HIIFormDataElementsStrings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} diff --git a/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.inf b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.inf new file mode 100644 index 0000000..b9c0652 --- /dev/null +++ b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.inf @@ -0,0 +1,22 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIFormDataElements + FILE_GUID = ab971f73-f582-4f90-a48d-88ff7c884bd9 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HIIFormDataElementsEntryPoint + UNLOAD_IMAGE = HIIFormDataElementsUnload + +[Sources] + HIIFormDataElements.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + HiiLib diff --git a/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Strings.uni b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Strings.uni new file mode 100644 index 0000000..6429f55 --- /dev/null +++ b/Lessons/Lesson_68/UefiLessonsPkg/HIIFormDataElements/Strings.uni @@ -0,0 +1,31 @@ +// +// Copyright (c) 2021, Konstantin Aladyshev <aladyshev22@gmail.com> +// +// SPDX-License-Identifier: MIT +// + +#langdef en-US "English" + +#string FORMSET_TITLE #language en-US "Simple Formset" +#string FORMSET_HELP #language en-US "This is a very simple formset" +#string FORMID1_TITLE #language en-US "Simple Form" +#string CHECKBOX_PROMPT #language en-US "Checkbox prompt" +#string CHECKBOX_HELP #language en-US "Checkbox help" +#string NUMERIC_PROMPT #language en-US "Numeric prompt" +#string NUMERIC_HELP #language en-US "Numeric help" +#string STRING_PROMPT #language en-US "String prompt" +#string STRING_HELP #language en-US "String help" +#string DATE_PROMPT #language en-US "Date prompt" +#string DATE_HELP #language en-US "Date help" +#string TIME_PROMPT #language en-US "Time prompt" +#string TIME_HELP #language en-US "Time help" +#string ONEOF_PROMPT #language en-US "OneOf list prompt" +#string ONEOF_HELP #language en-US "OneOf list help" +#string ONEOF_OPTION1 #language en-US "OneOf list option 1" +#string ONEOF_OPTION2 #language en-US "OneOf list option 2" +#string ONEOF_OPTION3 #language en-US "OneOf list option 3" +#string ORDERED_LIST_PROMPT #language en-US "Ordered list prompt" +#string ORDERED_LIST_HELP #language en-US "Ordered list help" +#string ORDERED_LIST_OPTION1 #language en-US "Ordered list option 1" +#string ORDERED_LIST_OPTION2 #language en-US "Ordered list option 2" +#string ORDERED_LIST_OPTION3 #language en-US "Ordered list option 3" |