diff options
author | Konstantin Aladyshev <aladyshev22@gmail.com> | 2022-09-23 18:03:02 +0300 |
---|---|---|
committer | Konstantin Aladyshev <aladyshev22@gmail.com> | 2022-09-23 18:03:02 +0300 |
commit | 31f41214bdeebda26e39daf776be8cb646d66666 (patch) | |
tree | 9b683dc408ea26b29fc5cc5dff4c0dcf5c184bce | |
parent | cd5821d17e5988fcc214f34e71bf1c89ffc85e6d (diff) | |
download | UEFI-Lessons-31f41214bdeebda26e39daf776be8cb646d66666.tar.gz UEFI-Lessons-31f41214bdeebda26e39daf776be8cb646d66666.tar.bz2 UEFI-Lessons-31f41214bdeebda26e39daf776be8cb646d66666.zip |
Add source code for UEFI Configuration language lessons
Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
19 files changed, 2061 insertions, 0 deletions
diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_5/UefiLessonsPkg/HIIConfig/HIIConfig.c b/Lessons_uncategorized/Lesson_Configuration_Language_5/UefiLessonsPkg/HIIConfig/HIIConfig.c new file mode 100644 index 0000000..3a2493b --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_5/UefiLessonsPkg/HIIConfig/HIIConfig.c @@ -0,0 +1,369 @@ +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/DevicePathLib.h> +#include <Library/HiiLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Protocol/HiiConfigRouting.h> + + +VOID PrintBuffer(UINT8* Buffer, UINTN Size) +{ + UINTN i = 0; + while (i < Size) { + Print(L"%02x ", Buffer[i]); + i++; + if (!(i%16)) { + Print(L" | "); + for (UINTN j=16; j>0; j--) + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + Print(L"\n"); + } + } + + if (i%16) { + for (UINTN j=0; j<=15; j++) { + if ((i+j)%16) + Print(L" "); + else + break; + } + Print(L" | "); + + for (UINTN j=(i%16); j>0; j--) { + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + } + Print(L"\n"); + } +} + +VOID ByteCfgStringToBuffer(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (UINTN Index = 0; Index < CfgStringLen; Index++) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if ((Index & 1) == 0) { + (*Buffer)[Index/2] = DigitUint8; + } else { + (*Buffer)[Index/2] = (UINT8)(((*Buffer)[Index/2] << 4) + DigitUint8); + } + } +} + +VOID ByteCfgStringToBufferReversed(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (INTN Index = (CfgStringLen-1); Index >= 0; Index--) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if (((CfgStringLen-1-Index) & 1) == 0) { + (*Buffer)[(CfgStringLen-1-Index)/2] = DigitUint8; + } else { + (*Buffer)[(CfgStringLen-1-Index)/2] = (UINT8)((DigitUint8 << 4) + (*Buffer)[(CfgStringLen-1-Index)/2]); + } + } +} + +EFI_STATUS GuidFromCfgString(CHAR16* CfgString, UINTN Size, EFI_GUID** Guid) +{ + UINTN GuidSize; + ByteCfgStringToBuffer(CfgString, Size, (UINT8**)Guid, &GuidSize); + if (GuidSize != sizeof(EFI_GUID)) + return EFI_NOT_FOUND; + return EFI_SUCCESS; +} + +EFI_STATUS DevicePathFromCfgString(CHAR16* CfgString, UINTN Size, EFI_DEVICE_PATH_PROTOCOL** DevicePath) +{ + UINTN DevicePathSize; + ByteCfgStringToBuffer(CfgString, Size, (UINT8**)DevicePath, &DevicePathSize); + + EFI_DEVICE_PATH_PROTOCOL* DevicePathTest = *DevicePath; + while (!IsDevicePathEnd(DevicePathTest)) { + if ((DevicePathTest->Type == 0) || (DevicePathTest->SubType == 0) || (DevicePathNodeLength(DevicePathTest) < sizeof(EFI_DEVICE_PATH_PROTOCOL))) + return EFI_NOT_FOUND; + DevicePathTest = NextDevicePathNode (DevicePathTest); + } + + return EFI_SUCCESS; +} + +EFI_STATUS NameFromCfgString(CHAR16* CfgString, UINTN Size, CHAR16** Name) +{ + *Name = AllocateZeroPool(Size * sizeof(CHAR16)); + CHAR16 TempStr[4]; + for (UINTN i=0; i<Size; i+=4) { + StrnCpyS(TempStr, sizeof(TempStr), CfgString+i, 4); + (*Name)[i/4] = (CHAR16)StrHexToUint64(TempStr); + } + return EFI_SUCCESS; +} + +VOID PrintLongString(CHAR16* Str) +{ + UINT32 MaxPrintBufferSize = PcdGet32(PcdUefiLibMaxPrintBufferSize); + if (StrLen(Str) > MaxPrintBufferSize) { + EFI_STRING TempStr = (EFI_STRING)AllocateZeroPool(MaxPrintBufferSize * sizeof (CHAR16)); + CopyMem(TempStr, Str, MaxPrintBufferSize * sizeof (CHAR16)); + TempStr[MaxPrintBufferSize-1]=0; + TempStr[MaxPrintBufferSize-2]=L'>'; + TempStr[MaxPrintBufferSize-3]=L'.'; + TempStr[MaxPrintBufferSize-4]=L'.'; + TempStr[MaxPrintBufferSize-5]=L'.'; + TempStr[MaxPrintBufferSize-6]=L'<'; + Print(L"%s", TempStr); + FreePool(TempStr); + } else { + Print(L"%s", Str); + } +} + +VOID PrintConfigSubString( + IN EFI_STRING ConfigString + ) +{ + EFI_STATUS Status; + if (StrStr(ConfigString, L"GUID=")) { + Print(L"\n"); + EFI_GUID* Guid; + Status = GuidFromCfgString(&ConfigString[StrLen(L"GUID=")], StrLen(ConfigString) - StrLen(L"GUID="), &Guid); + if (!EFI_ERROR(Status)) + Print(L"%s (%g)\n", ConfigString, Guid); + else + Print(L"%s\n", ConfigString); + FreePool(Guid); + } else if (StrStr(ConfigString, L"NAME=")) { + CHAR16* Name; + NameFromCfgString(&ConfigString[StrLen(L"NAME=")], StrLen(ConfigString) - StrLen(L"NAME="), &Name); + Print(L"%s (%s)\n", ConfigString, Name); + FreePool(Name); + } else if (StrStr(ConfigString, L"PATH=")) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + Status = DevicePathFromCfgString(&ConfigString[StrLen(L"PATH=")], StrLen(ConfigString) - StrLen(L"PATH="), &DevicePath); + if (!EFI_ERROR(Status)) + Print(L"%s (%s)\n", ConfigString, ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*) DevicePath, FALSE, FALSE)); + else + Print(L"%s\n", ConfigString); + FreePool(DevicePath); + } else if (StrStr(ConfigString, L"VALUE=")) { + PrintLongString(ConfigString); + Print(L"\n"); + UINT8* Buffer; + UINTN BufferSize; + ByteCfgStringToBufferReversed(&ConfigString[StrLen(L"VALUE=")], StrLen(&ConfigString[StrLen(L"VALUE=")]), &Buffer, &BufferSize); + PrintBuffer(Buffer, BufferSize); + FreePool(Buffer); + } else if (StrStr(ConfigString, L"OFFSET=") || StrStr(ConfigString, L"WIDTH=")) { + Print(L"%s ", ConfigString); + } else { + Print(L"%s\n", ConfigString); + } +} + +VOID PrintConfigString( + IN EFI_STRING ConfigString + ) +{ + UINTN StartIndex=0; + for (UINTN i=0; ConfigString[i] != 0; i++) { + if (ConfigString[i] == L'&') { + ConfigString[i] = 0; + PrintConfigSubString(&ConfigString[StartIndex]); + StartIndex = i+1; + } + } + PrintConfigSubString(&ConfigString[StartIndex]); +} + +EFI_STATUS CreateCfgHeader(EFI_STRING GuidStr, EFI_STRING NameStr, EFI_STRING DevicePathStr, EFI_STRING* Request) +{ + EFI_STATUS Status; + EFI_GUID FormsetGuid; + Status = StrToGuid(GuidStr, &FormsetGuid); + if (Status != RETURN_SUCCESS) { + Print(L"Error! Can't convert <FormsetGuid> argument to GUID\n"); + return EFI_INVALID_PARAMETER; + } + + EFI_HANDLE DriverHandle = NULL; + EFI_DEVICE_PATH_PROTOCOL* DevicePath = ConvertTextToDevicePath(DevicePathStr); + + Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, + &DevicePath, + &DriverHandle + ); + FreePool(DevicePath); + if (EFI_ERROR(Status) || (DriverHandle == NULL)) { + Print(L"Error! Can't get DriverHandle\n"); + return EFI_INVALID_PARAMETER; + } + + *Request = HiiConstructConfigHdr(&FormsetGuid, NameStr, DriverHandle); + return EFI_SUCCESS; +} + +VOID Usage() +{ + Print(L"Usage:\n"); + Print(L"HIIConfig.efi dump\n"); + Print(L"HIIConfig.efi extract <ConfigStr>\n"); + Print(L"HIIConfig.efi extract <Guid> <Name> <Path>\n"); + Print(L"HIIConfig.efi extract <Guid> <Name> <Path> <Offset> <Width>\n"); + Print(L"HIIConfig.efi route <ConfigStr>\n"); + Print(L"HIIConfig.efi route <Guid> <Name> <Path> <Offset> <Width> <Value>\n"); +} + +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting = NULL; + EFI_STATUS Status = gBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID **)&gHiiConfigRouting); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't locate gEfiHiiConfigRoutingProtocolGuid: %r", Status); + return Status; + } + + if (Argc == 1) { + Usage(); + return EFI_SUCCESS; + } + + + EFI_STRING Request; + EFI_STRING Progress; + EFI_STRING Result; + if (!StrCmp(Argv[1], L"dump")) { + Status = gHiiConfigRouting->ExportConfig(gHiiConfigRouting, &Result); + Print(L"Full configuration for the HII Database (Size = %d):\n", StrLen(Result)); + PrintConfigString(Result); + FreePool(Result); + } else if (!StrCmp(Argv[1], L"extract")) { + if (Argc == 3) { + Request = Argv[2]; + } else if ((Argc == 5) || (Argc == 7)) { + Status = CreateCfgHeader(Argv[2], Argv[3], Argv[4], &Request); + if (EFI_ERROR(Status)) { + return Status; + } + if (Argc == 7) { + EFI_STRING OffsetStr = Argv[5]; + EFI_STRING WidthStr = Argv[6]; + UINTN Size = (StrLen(Request) + StrLen(L"&OFFSET=") + StrLen(OffsetStr) + StrLen(L"&WIDTH=") + StrLen(WidthStr) + 1) * sizeof(CHAR16); + EFI_STRING TempRequest = AllocateZeroPool(Size); + UnicodeSPrint(TempRequest, Size, L"%s&OFFSET=%s&WIDTH=%s", Request, OffsetStr, WidthStr); + FreePool(Request); + Request = TempRequest; + } + Print(L"Request: %s\n", Request); + } else { + Print(L"Error! Wrong arguments\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + + Status = gHiiConfigRouting->ExtractConfig(gHiiConfigRouting, + Request, + &Progress, + &Result); + + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed %s\n", Progress); + } + + if (Argc >= 5) + FreePool(Request); + + if (EFI_ERROR(Status)) { + Print(L"Error! ExtractConfig returned %r\n", Status); + return Status; + } + Print(L"Response: "); + PrintLongString(Result); +/* If you want to get buffer for current value, you can do it like this: + + if (Argc == 7) { + Print(L"\n\nCurrent value:\n"); + CHAR16* StartPtr = StrStr(Result, L"VALUE="); + StartPtr += StrLen(L"VALUE="); + CHAR16* EndPtr = StartPtr; + while ((*EndPtr != 0) && (*EndPtr != L'&')) + EndPtr++; + + UINT8* Buffer; + UINTN BufferSize; + ByteCfgStringToBufferReversed(StartPtr, EndPtr-StartPtr, &Buffer, &BufferSize); + PrintBuffer(Buffer, BufferSize); + FreePool(Buffer); + } +*/ + Print(L"\n\n"); + PrintConfigString(Result); + FreePool(Result); + } else if (!StrCmp(Argv[1], L"route")) { + if (Argc == 3) { + Request = Argv[2]; + } else if (Argc == 8) { + Status = CreateCfgHeader(Argv[2], Argv[3], Argv[4], &Request); + if (EFI_ERROR(Status)) { + return Status; + } + EFI_STRING OffsetStr = Argv[5]; + EFI_STRING WidthStr = Argv[6]; + EFI_STRING ValueStr = Argv[7]; + UINTN Size = (StrLen(Request) + StrLen(L"&OFFSET=") + StrLen(OffsetStr) + StrLen(L"&WIDTH=") + StrLen(WidthStr) + + StrLen(L"&VALUE=") + StrLen(ValueStr) + 1) * sizeof(CHAR16); + EFI_STRING TempRequest = AllocateZeroPool(Size); + UnicodeSPrint(TempRequest, Size, L"%s&OFFSET=%s&WIDTH=%s&VALUE=%s", Request, OffsetStr, WidthStr, ValueStr); + FreePool(Request); + Request = TempRequest; + } else { + Print(L"Error! Wrong arguments\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + Print(L"Request: %s\n", Request); + + Status = gHiiConfigRouting->RouteConfig(gHiiConfigRouting, + Request, + &Progress); + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed: %s\n", Progress); + if (StrCmp(Progress, Request)) { + Print(L"IMPORTANT: part of the data was written!\n"); + } + } + if (Argc == 8) { + FreePool(Request); + } + if (EFI_ERROR(Status)) { + Print(L"Error! RouteConfig returned %r\n", Status); + return Status; + } + FreePool(Result); + } else { + Print(L"Error! Wrong arguments\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_5/UefiLessonsPkg/HIIConfig/HIIConfig.inf b/Lessons_uncategorized/Lesson_Configuration_Language_5/UefiLessonsPkg/HIIConfig/HIIConfig.inf new file mode 100644 index 0000000..6a1f99e --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_5/UefiLessonsPkg/HIIConfig/HIIConfig.inf @@ -0,0 +1,27 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIConfig + FILE_GUID = 417bf8bf-05b6-4cb5-b6e1-ed41c1fc971d + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + HIIConfig.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + ShellCEntryLib + UefiLib + DevicePathLib + HiiLib + +[Protocols] + gEfiHiiConfigRoutingProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize + diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Data.h b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Data.h new file mode 100644 index 0000000..eb9f369 --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Data.h @@ -0,0 +1,25 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0x531bc507, 0x9191, 0x4fa2, {0x94, 0x46, 0xb8, 0x44, 0xe3, 0x5d, 0xd1, 0x2a}} +#define DATAPATH_GUID {0xc299f575, 0xf1dd, 0x4d7d, {0xb7, 0xaa, 0xe5, 0x06, 0x4b, 0x3e, 0xcb, 0xd7}} +#define STORAGE_GUID {0xd2ae39c7, 0xe8dd, 0x4ab8, {0xad, 0x83, 0x7a, 0x57, 0xfe, 0x0e, 0x7e, 0xa8}} + +#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() + +#define LABEL_START 0x1111 +#define LABEL_END 0x2222 + +#endif diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Form.vfr b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Form.vfr new file mode 100644 index 0000000..930a84a --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Form.vfr @@ -0,0 +1,106 @@ +#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 = STORAGE_GUID; + + defaultstore StandardDefault, + prompt = STRING_TOKEN(STANDARD_DEFAULT_PROMPT), + attribute = 0x0000; + + defaultstore ManufactureDefault, + prompt = STRING_TOKEN(MFG_DEFAULT_PROMPT), + attribute = 0x0001; + + form + formid = 1, + title = STRING_TOKEN(FORMID1_TITLE); + + checkbox + varid = FormData.CheckboxValue, + prompt = STRING_TOKEN(CHECKBOX_PROMPT), + help = STRING_TOKEN(CHECKBOX_HELP), + default = TRUE, defaultstore = StandardDefault, + default = FALSE, defaultstore = ManufactureDefault, + endcheckbox; + + numeric + name = NumericQuestion, + varid = FormData.NumericValue, + prompt = STRING_TOKEN(NUMERIC_PROMPT), + help = STRING_TOKEN(NUMERIC_HELP), + flags = NUMERIC_SIZE_2 | DISPLAY_UINT_HEX, + //minimum = 0x1234, + //maximum = 0xaa55, + minimum = 0, + maximum = 10, + step = 1, + default = 7, defaultstore = StandardDefault, + default = 8, defaultstore = ManufactureDefault, + endnumeric; + + string + name = StringQuestion, + varid = FormData.StringValue, + prompt = STRING_TOKEN(STRING_PROMPT), + help = STRING_TOKEN(STRING_HELP), + minsize = 5, + maxsize = 10, + default = STRING_TOKEN(STRING_DEFAULT), defaultstore = StandardDefault, + default = STRING_TOKEN(STRING_PROMPT), defaultstore = ManufactureDefault, + endstring; + + date + varid = FormData.DateValue, + prompt = STRING_TOKEN(DATE_PROMPT), + help = STRING_TOKEN(DATE_HELP), + default = 2021/05/22, + enddate; + + time + varid = FormData.TimeValue, + prompt = STRING_TOKEN(TIME_PROMPT), + help = STRING_TOKEN(TIME_HELP), + default = 23:55:33, + endtime; + + oneof + name = OneOfQuestion, + varid = FormData.OneOfValue, + prompt = STRING_TOKEN(ONEOF_PROMPT), + help = STRING_TOKEN(ONEOF_HELP), + option text = STRING_TOKEN(ONEOF_OPTION1), value = 0x00, flags = 0; + option text = STRING_TOKEN(ONEOF_OPTION2), value = 0x33, flags = MANUFACTURING; + option text = STRING_TOKEN(ONEOF_OPTION3), value = 0x55, flags = DEFAULT; + 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; + default = {0x0c, 0x0b, 0x0a}, + endlist; + + resetbutton + defaultstore = StandardDefault, + prompt = STRING_TOKEN(BTN_STANDARD_DEFAULT_PROMPT), + help = STRING_TOKEN(BTN_STANDARD_DEFAULT_HELP), + endresetbutton; + + resetbutton + defaultstore = ManufactureDefault, + prompt = STRING_TOKEN(BTN_MFG_DEFAULT_PROMPT), + help = STRING_TOKEN(BTN_MFG_DEFAULT_HELP), + endresetbutton; + endform; +endformset; diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.c b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.c new file mode 100644 index 0000000..23b1db3 --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.c @@ -0,0 +1,141 @@ +#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) + } + }, + DATAPATH_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_GUID UEFIVariableGuid = STORAGE_GUID; + + +EFI_STATUS +EFIAPI +HIIFormDataElementsWithKeywordsUnload ( + 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, + &UEFIVariableGuid, + NULL, + &BufferSize, + &EfiVarstore); + if (!EFI_ERROR(Status)) { + Status = gRT->SetVariable( + UEFIVariableName, + &UEFIVariableGuid, + 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 +HIIFormDataElementsWithKeywordsEntryPoint ( + 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, + &UEFIVariableGuid, + NULL, + &BufferSize, + &EfiVarstore); + if (EFI_ERROR(Status)) { + ZeroMem(&EfiVarstore, sizeof(EfiVarstore)); + Status = gRT->SetVariable( + UEFIVariableName, + &UEFIVariableGuid, + 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, + HIIFormDataElementsWithKeywordsStrings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.inf b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.inf new file mode 100644 index 0000000..a75faa9 --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.inf @@ -0,0 +1,24 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIFormDataElementsWithKeywords + FILE_GUID = 162201c9-1208-4567-bab6-e9d32ae90e84 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HIIFormDataElementsWithKeywordsEntryPoint + UNLOAD_IMAGE = HIIFormDataElementsWithKeywordsUnload + +[Sources] + HIIFormDataElementsWithKeywords.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiLessonsPkg/UefiLessonsPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + HiiLib + diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Strings.uni b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Strings.uni new file mode 100644 index 0000000..10a410e --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Strings.uni @@ -0,0 +1,46 @@ +// +// Copyright (c) 2021, Konstantin Aladyshev <aladyshev22@gmail.com> +// +// SPDX-License-Identifier: MIT +// + +#langdef en-US "English" +#langdef x-UEFI-OEM "OEM_NameSpace" + +#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" + #language x-UEFI-OEM "CheckboxKey" +#string CHECKBOX_HELP #language en-US "Checkbox help" +#string NUMERIC_PROMPT #language en-US "Numeric prompt" + #language x-UEFI-OEM "NumericKey" +#string NUMERIC_HELP #language en-US "Numeric help" +#string STRING_PROMPT #language en-US "String prompt" + #language x-UEFI-OEM "StringKey" +#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" +#string WARNING_IF_PROMPT #language en-US "WarningIf prompt" +#string NOSUBMIT_IF_PROMPT #language en-US "NoSubmitIf prompt" +#string INCONSISTENT_IF_PROMPT #language en-US "InconsistentIf prompt" +#string TEST_STRING #language en-US "EDKII" +#string STRING_DEFAULT #language en-US "String default" +#string STANDARD_DEFAULT_PROMPT #language en-US "Standard default" +#string MFG_DEFAULT_PROMPT #language en-US "Manufacture default" +#string BTN_STANDARD_DEFAULT_PROMPT #language en-US "Reset to standard default prompt" +#string BTN_STANDARD_DEFAULT_HELP #language en-US "Reset to standard default help" +#string BTN_MFG_DEFAULT_PROMPT #language en-US "Reset to manufacture default prompt" +#string BTN_MFG_DEFAULT_HELP #language en-US "Reset to manufacture default help" diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIKeyword/HIIKeyword.c b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIKeyword/HIIKeyword.c new file mode 100644 index 0000000..00575a7 --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIKeyword/HIIKeyword.c @@ -0,0 +1,267 @@ +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Protocol/HiiConfigKeyword.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DevicePathLib.h> + +VOID PrintBuffer(UINT8* Buffer, UINTN Size) +{ + UINTN i = 0; + while (i < Size) { + Print(L"%02x ", Buffer[i]); + i++; + if (!(i%16)) { + Print(L" | "); + for (UINTN j=16; j>0; j--) + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + Print(L"\n"); + } + } + + if (i%16) { + for (UINTN j=0; j<=15; j++) { + if ((i+j)%16) + Print(L" "); + else + break; + } + Print(L" | "); + + for (UINTN j=(i%16); j>0; j--) { + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + } + Print(L"\n"); + } +} + +VOID ByteCfgStringToBuffer(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (UINTN Index = 0; Index < CfgStringLen; Index++) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if ((Index & 1) == 0) { + (*Buffer)[Index/2] = DigitUint8; + } else { + (*Buffer)[Index/2] = (UINT8)(((*Buffer)[Index/2] << 4) + DigitUint8); + } + } +} + +VOID ByteCfgStringToBufferReversed(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (INTN Index = (CfgStringLen-1); Index >= 0; Index--) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if (((CfgStringLen-1-Index) & 1) == 0) { + (*Buffer)[(CfgStringLen-1-Index)/2] = DigitUint8; + } else { + (*Buffer)[(CfgStringLen-1-Index)/2] = (UINT8)((DigitUint8 << 4) + (*Buffer)[(CfgStringLen-1-Index)/2]); + } + } +} + +EFI_STATUS DevicePathFromCfgString(CHAR16* CfgString, UINTN Size, EFI_DEVICE_PATH_PROTOCOL** DevicePath) +{ + UINTN DevicePathSize; + ByteCfgStringToBuffer(CfgString, Size, (UINT8**)DevicePath, &DevicePathSize); + + EFI_DEVICE_PATH_PROTOCOL* DevicePathTest = *DevicePath; + while (!IsDevicePathEnd(DevicePathTest)) { + if ((DevicePathTest->Type == 0) || (DevicePathTest->SubType == 0) || (DevicePathNodeLength(DevicePathTest) < sizeof(EFI_DEVICE_PATH_PROTOCOL))) + return EFI_NOT_FOUND; + DevicePathTest = NextDevicePathNode (DevicePathTest); + } + + return EFI_SUCCESS; +} + +VOID PrintLongString(CHAR16* Str) +{ + UINT32 MaxPrintBufferSize = PcdGet32(PcdUefiLibMaxPrintBufferSize); + if (StrLen(Str) > MaxPrintBufferSize) { + EFI_STRING TempStr = (EFI_STRING)AllocateZeroPool(MaxPrintBufferSize * sizeof (CHAR16)); + CopyMem(TempStr, Str, MaxPrintBufferSize * sizeof (CHAR16)); + TempStr[MaxPrintBufferSize-1]=0; + TempStr[MaxPrintBufferSize-2]=L'>'; + TempStr[MaxPrintBufferSize-3]=L'.'; + TempStr[MaxPrintBufferSize-4]=L'.'; + TempStr[MaxPrintBufferSize-5]=L'.'; + TempStr[MaxPrintBufferSize-6]=L'<'; + Print(L"%s", TempStr); + FreePool(TempStr); + } else { + Print(L"%s", Str); + } +} + +VOID PrintConfigSubString( + IN EFI_STRING ConfigString + ) +{ + EFI_STATUS Status; + if (StrStr(ConfigString, L"NAMESPACE=")) { + Print(L"\n"); + Print(L"%s\n", ConfigString); + } else if (StrStr(ConfigString, L"PATH=")) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + Status = DevicePathFromCfgString(&ConfigString[StrLen(L"PATH=")], StrLen(ConfigString) - StrLen(L"PATH="), &DevicePath); + if (!EFI_ERROR(Status)) + Print(L"%s (%s)\n", ConfigString, ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*) DevicePath, FALSE, FALSE)); + else + Print(L"%s\n", ConfigString); + FreePool(DevicePath); + } else if (StrStr(ConfigString, L"VALUE=")) { + PrintLongString(ConfigString); + Print(L"\n"); + UINT8* Buffer; + UINTN BufferSize; + ByteCfgStringToBufferReversed(&ConfigString[StrLen(L"VALUE=")], StrLen(&ConfigString[StrLen(L"VALUE=")]), &Buffer, &BufferSize); + PrintBuffer(Buffer, BufferSize); + FreePool(Buffer); + } else { + Print(L"%s\n", ConfigString); + } +} + +VOID PrintConfigString( + IN EFI_STRING ConfigString + ) +{ + UINTN StartIndex=0; + for (UINTN i=0; ConfigString[i] != 0; i++) { + if (ConfigString[i] == L'&') { + ConfigString[i] = 0; + PrintConfigSubString(&ConfigString[StartIndex]); + StartIndex = i+1; + } + } + PrintConfigSubString(&ConfigString[StartIndex]); +} + +EFI_STRING ProgressErrorStr(UINT32 ProgressErr) +{ + switch (ProgressErr) { + case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND: + return L"NamespaceId not found\n"; + case KEYWORD_HANDLER_MALFORMED_STRING: + return L"Malformed string\n"; + case KEYWORD_HANDLER_KEYWORD_NOT_FOUND: + return L"Keyword not found\n"; + case KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED: + return L"Incompatible value detected\n"; + case KEYWORD_HANDLER_ACCESS_NOT_PERMITTED: + return L"Access not permitted\n"; + default: + return L"Unknown error\n"; + } +} + +VOID Usage() +{ + Print(L"Usage:\n"); + Print(L"HIIKeyword get <NamespaceStr> <KeywordStr>\n"); + Print(L"HIIKeyword set <KeywordStr>\n"); +} + +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *gHiiConfigKeywordHandler = NULL; + EFI_STATUS Status = gBS->LocateProtocol(&gEfiConfigKeywordHandlerProtocolGuid, + NULL, + (VOID **)&gHiiConfigKeywordHandler); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't locate gEfiConfigKeywordHandlerProtocolGuid: %r", Status); + return Status; + } + + if (Argc==1) { + Usage(); + return EFI_SUCCESS; + } + + EFI_STRING Progress; + UINT32 ProgressErr; + if (!StrCmp(Argv[1], L"get")) { + if (Argc != 4) { + Print(L"Wrong argument!\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + EFI_STRING NameSpaceId = Argv[2]; + EFI_STRING KeywordString = Argv[3]; + if (!StrCmp(NameSpaceId, L'\0')) { + NameSpaceId = NULL; + } + if (!StrCmp(KeywordString, L'\0')) { + KeywordString = NULL; + } + + EFI_STRING Results; + Status = gHiiConfigKeywordHandler->GetData(gHiiConfigKeywordHandler, + NameSpaceId, + KeywordString, + &Progress, + &ProgressErr, + &Results); + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed %s\n", Progress); + } + if (ProgressErr) { + Print(L"Error! ProgressErr=%s\n", ProgressErrorStr(ProgressErr)); + } + if (EFI_ERROR(Status)) { + Print(L"Error! GetData returned %r\n", Status); + return Status; + } + Print(L"Response: "); + PrintLongString(Results); + Print(L"\n\n"); + PrintConfigString(Results); + FreePool(Results); + } else if (!StrCmp(Argv[1], L"set")) { + if (Argc != 3) { + Print(L"Wrong argument!\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + Status = gHiiConfigKeywordHandler->SetData(gHiiConfigKeywordHandler, + Argv[2], + &Progress, + &ProgressErr); + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed %s\n", Progress); + } + if (ProgressErr) { + Print(L"Error! ProgressErr=%s\n", ProgressErrorStr(ProgressErr)); + } + if (EFI_ERROR(Status)) { + Print(L"Error! SetData returned %r\n", Status); + return Status; + } + } else { + Print(L"Wrong argument!\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} diff --git a/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIKeyword/HIIKeyword.inf b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIKeyword/HIIKeyword.inf new file mode 100644 index 0000000..de46152 --- /dev/null +++ b/Lessons_uncategorized/Lesson_Configuration_Language_7/UefiLessonsPkg/HIIKeyword/HIIKeyword.inf @@ -0,0 +1,24 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIKeyword + FILE_GUID = a9ec2c65-7a2b-41b8-bab0-fb4ad8ecfdde + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + HIIKeyword.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + ShellCEntryLib + UefiLib + +[Protocols] + gEfiConfigKeywordHandlerProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize + diff --git a/UefiLessonsPkg/HIIConfig/HIIConfig.c b/UefiLessonsPkg/HIIConfig/HIIConfig.c new file mode 100644 index 0000000..3a2493b --- /dev/null +++ b/UefiLessonsPkg/HIIConfig/HIIConfig.c @@ -0,0 +1,369 @@ +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/DevicePathLib.h> +#include <Library/HiiLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Protocol/HiiConfigRouting.h> + + +VOID PrintBuffer(UINT8* Buffer, UINTN Size) +{ + UINTN i = 0; + while (i < Size) { + Print(L"%02x ", Buffer[i]); + i++; + if (!(i%16)) { + Print(L" | "); + for (UINTN j=16; j>0; j--) + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + Print(L"\n"); + } + } + + if (i%16) { + for (UINTN j=0; j<=15; j++) { + if ((i+j)%16) + Print(L" "); + else + break; + } + Print(L" | "); + + for (UINTN j=(i%16); j>0; j--) { + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + } + Print(L"\n"); + } +} + +VOID ByteCfgStringToBuffer(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (UINTN Index = 0; Index < CfgStringLen; Index++) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if ((Index & 1) == 0) { + (*Buffer)[Index/2] = DigitUint8; + } else { + (*Buffer)[Index/2] = (UINT8)(((*Buffer)[Index/2] << 4) + DigitUint8); + } + } +} + +VOID ByteCfgStringToBufferReversed(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (INTN Index = (CfgStringLen-1); Index >= 0; Index--) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if (((CfgStringLen-1-Index) & 1) == 0) { + (*Buffer)[(CfgStringLen-1-Index)/2] = DigitUint8; + } else { + (*Buffer)[(CfgStringLen-1-Index)/2] = (UINT8)((DigitUint8 << 4) + (*Buffer)[(CfgStringLen-1-Index)/2]); + } + } +} + +EFI_STATUS GuidFromCfgString(CHAR16* CfgString, UINTN Size, EFI_GUID** Guid) +{ + UINTN GuidSize; + ByteCfgStringToBuffer(CfgString, Size, (UINT8**)Guid, &GuidSize); + if (GuidSize != sizeof(EFI_GUID)) + return EFI_NOT_FOUND; + return EFI_SUCCESS; +} + +EFI_STATUS DevicePathFromCfgString(CHAR16* CfgString, UINTN Size, EFI_DEVICE_PATH_PROTOCOL** DevicePath) +{ + UINTN DevicePathSize; + ByteCfgStringToBuffer(CfgString, Size, (UINT8**)DevicePath, &DevicePathSize); + + EFI_DEVICE_PATH_PROTOCOL* DevicePathTest = *DevicePath; + while (!IsDevicePathEnd(DevicePathTest)) { + if ((DevicePathTest->Type == 0) || (DevicePathTest->SubType == 0) || (DevicePathNodeLength(DevicePathTest) < sizeof(EFI_DEVICE_PATH_PROTOCOL))) + return EFI_NOT_FOUND; + DevicePathTest = NextDevicePathNode (DevicePathTest); + } + + return EFI_SUCCESS; +} + +EFI_STATUS NameFromCfgString(CHAR16* CfgString, UINTN Size, CHAR16** Name) +{ + *Name = AllocateZeroPool(Size * sizeof(CHAR16)); + CHAR16 TempStr[4]; + for (UINTN i=0; i<Size; i+=4) { + StrnCpyS(TempStr, sizeof(TempStr), CfgString+i, 4); + (*Name)[i/4] = (CHAR16)StrHexToUint64(TempStr); + } + return EFI_SUCCESS; +} + +VOID PrintLongString(CHAR16* Str) +{ + UINT32 MaxPrintBufferSize = PcdGet32(PcdUefiLibMaxPrintBufferSize); + if (StrLen(Str) > MaxPrintBufferSize) { + EFI_STRING TempStr = (EFI_STRING)AllocateZeroPool(MaxPrintBufferSize * sizeof (CHAR16)); + CopyMem(TempStr, Str, MaxPrintBufferSize * sizeof (CHAR16)); + TempStr[MaxPrintBufferSize-1]=0; + TempStr[MaxPrintBufferSize-2]=L'>'; + TempStr[MaxPrintBufferSize-3]=L'.'; + TempStr[MaxPrintBufferSize-4]=L'.'; + TempStr[MaxPrintBufferSize-5]=L'.'; + TempStr[MaxPrintBufferSize-6]=L'<'; + Print(L"%s", TempStr); + FreePool(TempStr); + } else { + Print(L"%s", Str); + } +} + +VOID PrintConfigSubString( + IN EFI_STRING ConfigString + ) +{ + EFI_STATUS Status; + if (StrStr(ConfigString, L"GUID=")) { + Print(L"\n"); + EFI_GUID* Guid; + Status = GuidFromCfgString(&ConfigString[StrLen(L"GUID=")], StrLen(ConfigString) - StrLen(L"GUID="), &Guid); + if (!EFI_ERROR(Status)) + Print(L"%s (%g)\n", ConfigString, Guid); + else + Print(L"%s\n", ConfigString); + FreePool(Guid); + } else if (StrStr(ConfigString, L"NAME=")) { + CHAR16* Name; + NameFromCfgString(&ConfigString[StrLen(L"NAME=")], StrLen(ConfigString) - StrLen(L"NAME="), &Name); + Print(L"%s (%s)\n", ConfigString, Name); + FreePool(Name); + } else if (StrStr(ConfigString, L"PATH=")) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + Status = DevicePathFromCfgString(&ConfigString[StrLen(L"PATH=")], StrLen(ConfigString) - StrLen(L"PATH="), &DevicePath); + if (!EFI_ERROR(Status)) + Print(L"%s (%s)\n", ConfigString, ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*) DevicePath, FALSE, FALSE)); + else + Print(L"%s\n", ConfigString); + FreePool(DevicePath); + } else if (StrStr(ConfigString, L"VALUE=")) { + PrintLongString(ConfigString); + Print(L"\n"); + UINT8* Buffer; + UINTN BufferSize; + ByteCfgStringToBufferReversed(&ConfigString[StrLen(L"VALUE=")], StrLen(&ConfigString[StrLen(L"VALUE=")]), &Buffer, &BufferSize); + PrintBuffer(Buffer, BufferSize); + FreePool(Buffer); + } else if (StrStr(ConfigString, L"OFFSET=") || StrStr(ConfigString, L"WIDTH=")) { + Print(L"%s ", ConfigString); + } else { + Print(L"%s\n", ConfigString); + } +} + +VOID PrintConfigString( + IN EFI_STRING ConfigString + ) +{ + UINTN StartIndex=0; + for (UINTN i=0; ConfigString[i] != 0; i++) { + if (ConfigString[i] == L'&') { + ConfigString[i] = 0; + PrintConfigSubString(&ConfigString[StartIndex]); + StartIndex = i+1; + } + } + PrintConfigSubString(&ConfigString[StartIndex]); +} + +EFI_STATUS CreateCfgHeader(EFI_STRING GuidStr, EFI_STRING NameStr, EFI_STRING DevicePathStr, EFI_STRING* Request) +{ + EFI_STATUS Status; + EFI_GUID FormsetGuid; + Status = StrToGuid(GuidStr, &FormsetGuid); + if (Status != RETURN_SUCCESS) { + Print(L"Error! Can't convert <FormsetGuid> argument to GUID\n"); + return EFI_INVALID_PARAMETER; + } + + EFI_HANDLE DriverHandle = NULL; + EFI_DEVICE_PATH_PROTOCOL* DevicePath = ConvertTextToDevicePath(DevicePathStr); + + Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, + &DevicePath, + &DriverHandle + ); + FreePool(DevicePath); + if (EFI_ERROR(Status) || (DriverHandle == NULL)) { + Print(L"Error! Can't get DriverHandle\n"); + return EFI_INVALID_PARAMETER; + } + + *Request = HiiConstructConfigHdr(&FormsetGuid, NameStr, DriverHandle); + return EFI_SUCCESS; +} + +VOID Usage() +{ + Print(L"Usage:\n"); + Print(L"HIIConfig.efi dump\n"); + Print(L"HIIConfig.efi extract <ConfigStr>\n"); + Print(L"HIIConfig.efi extract <Guid> <Name> <Path>\n"); + Print(L"HIIConfig.efi extract <Guid> <Name> <Path> <Offset> <Width>\n"); + Print(L"HIIConfig.efi route <ConfigStr>\n"); + Print(L"HIIConfig.efi route <Guid> <Name> <Path> <Offset> <Width> <Value>\n"); +} + +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting = NULL; + EFI_STATUS Status = gBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID **)&gHiiConfigRouting); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't locate gEfiHiiConfigRoutingProtocolGuid: %r", Status); + return Status; + } + + if (Argc == 1) { + Usage(); + return EFI_SUCCESS; + } + + + EFI_STRING Request; + EFI_STRING Progress; + EFI_STRING Result; + if (!StrCmp(Argv[1], L"dump")) { + Status = gHiiConfigRouting->ExportConfig(gHiiConfigRouting, &Result); + Print(L"Full configuration for the HII Database (Size = %d):\n", StrLen(Result)); + PrintConfigString(Result); + FreePool(Result); + } else if (!StrCmp(Argv[1], L"extract")) { + if (Argc == 3) { + Request = Argv[2]; + } else if ((Argc == 5) || (Argc == 7)) { + Status = CreateCfgHeader(Argv[2], Argv[3], Argv[4], &Request); + if (EFI_ERROR(Status)) { + return Status; + } + if (Argc == 7) { + EFI_STRING OffsetStr = Argv[5]; + EFI_STRING WidthStr = Argv[6]; + UINTN Size = (StrLen(Request) + StrLen(L"&OFFSET=") + StrLen(OffsetStr) + StrLen(L"&WIDTH=") + StrLen(WidthStr) + 1) * sizeof(CHAR16); + EFI_STRING TempRequest = AllocateZeroPool(Size); + UnicodeSPrint(TempRequest, Size, L"%s&OFFSET=%s&WIDTH=%s", Request, OffsetStr, WidthStr); + FreePool(Request); + Request = TempRequest; + } + Print(L"Request: %s\n", Request); + } else { + Print(L"Error! Wrong arguments\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + + Status = gHiiConfigRouting->ExtractConfig(gHiiConfigRouting, + Request, + &Progress, + &Result); + + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed %s\n", Progress); + } + + if (Argc >= 5) + FreePool(Request); + + if (EFI_ERROR(Status)) { + Print(L"Error! ExtractConfig returned %r\n", Status); + return Status; + } + Print(L"Response: "); + PrintLongString(Result); +/* If you want to get buffer for current value, you can do it like this: + + if (Argc == 7) { + Print(L"\n\nCurrent value:\n"); + CHAR16* StartPtr = StrStr(Result, L"VALUE="); + StartPtr += StrLen(L"VALUE="); + CHAR16* EndPtr = StartPtr; + while ((*EndPtr != 0) && (*EndPtr != L'&')) + EndPtr++; + + UINT8* Buffer; + UINTN BufferSize; + ByteCfgStringToBufferReversed(StartPtr, EndPtr-StartPtr, &Buffer, &BufferSize); + PrintBuffer(Buffer, BufferSize); + FreePool(Buffer); + } +*/ + Print(L"\n\n"); + PrintConfigString(Result); + FreePool(Result); + } else if (!StrCmp(Argv[1], L"route")) { + if (Argc == 3) { + Request = Argv[2]; + } else if (Argc == 8) { + Status = CreateCfgHeader(Argv[2], Argv[3], Argv[4], &Request); + if (EFI_ERROR(Status)) { + return Status; + } + EFI_STRING OffsetStr = Argv[5]; + EFI_STRING WidthStr = Argv[6]; + EFI_STRING ValueStr = Argv[7]; + UINTN Size = (StrLen(Request) + StrLen(L"&OFFSET=") + StrLen(OffsetStr) + StrLen(L"&WIDTH=") + StrLen(WidthStr) + + StrLen(L"&VALUE=") + StrLen(ValueStr) + 1) * sizeof(CHAR16); + EFI_STRING TempRequest = AllocateZeroPool(Size); + UnicodeSPrint(TempRequest, Size, L"%s&OFFSET=%s&WIDTH=%s&VALUE=%s", Request, OffsetStr, WidthStr, ValueStr); + FreePool(Request); + Request = TempRequest; + } else { + Print(L"Error! Wrong arguments\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + Print(L"Request: %s\n", Request); + + Status = gHiiConfigRouting->RouteConfig(gHiiConfigRouting, + Request, + &Progress); + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed: %s\n", Progress); + if (StrCmp(Progress, Request)) { + Print(L"IMPORTANT: part of the data was written!\n"); + } + } + if (Argc == 8) { + FreePool(Request); + } + if (EFI_ERROR(Status)) { + Print(L"Error! RouteConfig returned %r\n", Status); + return Status; + } + FreePool(Result); + } else { + Print(L"Error! Wrong arguments\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/HIIConfig/HIIConfig.inf b/UefiLessonsPkg/HIIConfig/HIIConfig.inf new file mode 100644 index 0000000..6a1f99e --- /dev/null +++ b/UefiLessonsPkg/HIIConfig/HIIConfig.inf @@ -0,0 +1,27 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIConfig + FILE_GUID = 417bf8bf-05b6-4cb5-b6e1-ed41c1fc971d + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + HIIConfig.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + ShellCEntryLib + UefiLib + DevicePathLib + HiiLib + +[Protocols] + gEfiHiiConfigRoutingProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize + diff --git a/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Data.h b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Data.h new file mode 100644 index 0000000..eb9f369 --- /dev/null +++ b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Data.h @@ -0,0 +1,25 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0x531bc507, 0x9191, 0x4fa2, {0x94, 0x46, 0xb8, 0x44, 0xe3, 0x5d, 0xd1, 0x2a}} +#define DATAPATH_GUID {0xc299f575, 0xf1dd, 0x4d7d, {0xb7, 0xaa, 0xe5, 0x06, 0x4b, 0x3e, 0xcb, 0xd7}} +#define STORAGE_GUID {0xd2ae39c7, 0xe8dd, 0x4ab8, {0xad, 0x83, 0x7a, 0x57, 0xfe, 0x0e, 0x7e, 0xa8}} + +#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() + +#define LABEL_START 0x1111 +#define LABEL_END 0x2222 + +#endif diff --git a/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Form.vfr b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Form.vfr new file mode 100644 index 0000000..930a84a --- /dev/null +++ b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Form.vfr @@ -0,0 +1,106 @@ +#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 = STORAGE_GUID; + + defaultstore StandardDefault, + prompt = STRING_TOKEN(STANDARD_DEFAULT_PROMPT), + attribute = 0x0000; + + defaultstore ManufactureDefault, + prompt = STRING_TOKEN(MFG_DEFAULT_PROMPT), + attribute = 0x0001; + + form + formid = 1, + title = STRING_TOKEN(FORMID1_TITLE); + + checkbox + varid = FormData.CheckboxValue, + prompt = STRING_TOKEN(CHECKBOX_PROMPT), + help = STRING_TOKEN(CHECKBOX_HELP), + default = TRUE, defaultstore = StandardDefault, + default = FALSE, defaultstore = ManufactureDefault, + endcheckbox; + + numeric + name = NumericQuestion, + varid = FormData.NumericValue, + prompt = STRING_TOKEN(NUMERIC_PROMPT), + help = STRING_TOKEN(NUMERIC_HELP), + flags = NUMERIC_SIZE_2 | DISPLAY_UINT_HEX, + //minimum = 0x1234, + //maximum = 0xaa55, + minimum = 0, + maximum = 10, + step = 1, + default = 7, defaultstore = StandardDefault, + default = 8, defaultstore = ManufactureDefault, + endnumeric; + + string + name = StringQuestion, + varid = FormData.StringValue, + prompt = STRING_TOKEN(STRING_PROMPT), + help = STRING_TOKEN(STRING_HELP), + minsize = 5, + maxsize = 10, + default = STRING_TOKEN(STRING_DEFAULT), defaultstore = StandardDefault, + default = STRING_TOKEN(STRING_PROMPT), defaultstore = ManufactureDefault, + endstring; + + date + varid = FormData.DateValue, + prompt = STRING_TOKEN(DATE_PROMPT), + help = STRING_TOKEN(DATE_HELP), + default = 2021/05/22, + enddate; + + time + varid = FormData.TimeValue, + prompt = STRING_TOKEN(TIME_PROMPT), + help = STRING_TOKEN(TIME_HELP), + default = 23:55:33, + endtime; + + oneof + name = OneOfQuestion, + varid = FormData.OneOfValue, + prompt = STRING_TOKEN(ONEOF_PROMPT), + help = STRING_TOKEN(ONEOF_HELP), + option text = STRING_TOKEN(ONEOF_OPTION1), value = 0x00, flags = 0; + option text = STRING_TOKEN(ONEOF_OPTION2), value = 0x33, flags = MANUFACTURING; + option text = STRING_TOKEN(ONEOF_OPTION3), value = 0x55, flags = DEFAULT; + 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; + default = {0x0c, 0x0b, 0x0a}, + endlist; + + resetbutton + defaultstore = StandardDefault, + prompt = STRING_TOKEN(BTN_STANDARD_DEFAULT_PROMPT), + help = STRING_TOKEN(BTN_STANDARD_DEFAULT_HELP), + endresetbutton; + + resetbutton + defaultstore = ManufactureDefault, + prompt = STRING_TOKEN(BTN_MFG_DEFAULT_PROMPT), + help = STRING_TOKEN(BTN_MFG_DEFAULT_HELP), + endresetbutton; + endform; +endformset; diff --git a/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.c b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.c new file mode 100644 index 0000000..23b1db3 --- /dev/null +++ b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.c @@ -0,0 +1,141 @@ +#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) + } + }, + DATAPATH_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_GUID UEFIVariableGuid = STORAGE_GUID; + + +EFI_STATUS +EFIAPI +HIIFormDataElementsWithKeywordsUnload ( + 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, + &UEFIVariableGuid, + NULL, + &BufferSize, + &EfiVarstore); + if (!EFI_ERROR(Status)) { + Status = gRT->SetVariable( + UEFIVariableName, + &UEFIVariableGuid, + 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 +HIIFormDataElementsWithKeywordsEntryPoint ( + 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, + &UEFIVariableGuid, + NULL, + &BufferSize, + &EfiVarstore); + if (EFI_ERROR(Status)) { + ZeroMem(&EfiVarstore, sizeof(EfiVarstore)); + Status = gRT->SetVariable( + UEFIVariableName, + &UEFIVariableGuid, + 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, + HIIFormDataElementsWithKeywordsStrings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.inf b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.inf new file mode 100644 index 0000000..a75faa9 --- /dev/null +++ b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.inf @@ -0,0 +1,24 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIFormDataElementsWithKeywords + FILE_GUID = 162201c9-1208-4567-bab6-e9d32ae90e84 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HIIFormDataElementsWithKeywordsEntryPoint + UNLOAD_IMAGE = HIIFormDataElementsWithKeywordsUnload + +[Sources] + HIIFormDataElementsWithKeywords.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiLessonsPkg/UefiLessonsPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + HiiLib + diff --git a/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Strings.uni b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Strings.uni new file mode 100644 index 0000000..10a410e --- /dev/null +++ b/UefiLessonsPkg/HIIFormDataElementsWithKeywords/Strings.uni @@ -0,0 +1,46 @@ +// +// Copyright (c) 2021, Konstantin Aladyshev <aladyshev22@gmail.com> +// +// SPDX-License-Identifier: MIT +// + +#langdef en-US "English" +#langdef x-UEFI-OEM "OEM_NameSpace" + +#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" + #language x-UEFI-OEM "CheckboxKey" +#string CHECKBOX_HELP #language en-US "Checkbox help" +#string NUMERIC_PROMPT #language en-US "Numeric prompt" + #language x-UEFI-OEM "NumericKey" +#string NUMERIC_HELP #language en-US "Numeric help" +#string STRING_PROMPT #language en-US "String prompt" + #language x-UEFI-OEM "StringKey" +#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" +#string WARNING_IF_PROMPT #language en-US "WarningIf prompt" +#string NOSUBMIT_IF_PROMPT #language en-US "NoSubmitIf prompt" +#string INCONSISTENT_IF_PROMPT #language en-US "InconsistentIf prompt" +#string TEST_STRING #language en-US "EDKII" +#string STRING_DEFAULT #language en-US "String default" +#string STANDARD_DEFAULT_PROMPT #language en-US "Standard default" +#string MFG_DEFAULT_PROMPT #language en-US "Manufacture default" +#string BTN_STANDARD_DEFAULT_PROMPT #language en-US "Reset to standard default prompt" +#string BTN_STANDARD_DEFAULT_HELP #language en-US "Reset to standard default help" +#string BTN_MFG_DEFAULT_PROMPT #language en-US "Reset to manufacture default prompt" +#string BTN_MFG_DEFAULT_HELP #language en-US "Reset to manufacture default help" diff --git a/UefiLessonsPkg/HIIKeyword/HIIKeyword.c b/UefiLessonsPkg/HIIKeyword/HIIKeyword.c new file mode 100644 index 0000000..00575a7 --- /dev/null +++ b/UefiLessonsPkg/HIIKeyword/HIIKeyword.c @@ -0,0 +1,267 @@ +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Protocol/HiiConfigKeyword.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DevicePathLib.h> + +VOID PrintBuffer(UINT8* Buffer, UINTN Size) +{ + UINTN i = 0; + while (i < Size) { + Print(L"%02x ", Buffer[i]); + i++; + if (!(i%16)) { + Print(L" | "); + for (UINTN j=16; j>0; j--) + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + Print(L"\n"); + } + } + + if (i%16) { + for (UINTN j=0; j<=15; j++) { + if ((i+j)%16) + Print(L" "); + else + break; + } + Print(L" | "); + + for (UINTN j=(i%16); j>0; j--) { + if ((Buffer[i-j] >= 0x20) && (Buffer[i-j] < 0x7E)) + Print(L"%c", Buffer[i-j]); + else + Print(L"."); + } + Print(L"\n"); + } +} + +VOID ByteCfgStringToBuffer(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (UINTN Index = 0; Index < CfgStringLen; Index++) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if ((Index & 1) == 0) { + (*Buffer)[Index/2] = DigitUint8; + } else { + (*Buffer)[Index/2] = (UINT8)(((*Buffer)[Index/2] << 4) + DigitUint8); + } + } +} + +VOID ByteCfgStringToBufferReversed(CHAR16* CfgString, UINTN CfgStringLen, UINT8** Buffer, UINTN* BufferSize) +{ + *BufferSize = (CfgStringLen + 1) / 2; + *Buffer = (UINT8*)AllocateZeroPool(*BufferSize); + UINT8 DigitUint8; + CHAR16 TempStr[2] = {0}; + for (INTN Index = (CfgStringLen-1); Index >= 0; Index--) { + TempStr[0] = CfgString[Index]; + DigitUint8 = (UINT8)StrHexToUint64(TempStr); + if (((CfgStringLen-1-Index) & 1) == 0) { + (*Buffer)[(CfgStringLen-1-Index)/2] = DigitUint8; + } else { + (*Buffer)[(CfgStringLen-1-Index)/2] = (UINT8)((DigitUint8 << 4) + (*Buffer)[(CfgStringLen-1-Index)/2]); + } + } +} + +EFI_STATUS DevicePathFromCfgString(CHAR16* CfgString, UINTN Size, EFI_DEVICE_PATH_PROTOCOL** DevicePath) +{ + UINTN DevicePathSize; + ByteCfgStringToBuffer(CfgString, Size, (UINT8**)DevicePath, &DevicePathSize); + + EFI_DEVICE_PATH_PROTOCOL* DevicePathTest = *DevicePath; + while (!IsDevicePathEnd(DevicePathTest)) { + if ((DevicePathTest->Type == 0) || (DevicePathTest->SubType == 0) || (DevicePathNodeLength(DevicePathTest) < sizeof(EFI_DEVICE_PATH_PROTOCOL))) + return EFI_NOT_FOUND; + DevicePathTest = NextDevicePathNode (DevicePathTest); + } + + return EFI_SUCCESS; +} + +VOID PrintLongString(CHAR16* Str) +{ + UINT32 MaxPrintBufferSize = PcdGet32(PcdUefiLibMaxPrintBufferSize); + if (StrLen(Str) > MaxPrintBufferSize) { + EFI_STRING TempStr = (EFI_STRING)AllocateZeroPool(MaxPrintBufferSize * sizeof (CHAR16)); + CopyMem(TempStr, Str, MaxPrintBufferSize * sizeof (CHAR16)); + TempStr[MaxPrintBufferSize-1]=0; + TempStr[MaxPrintBufferSize-2]=L'>'; + TempStr[MaxPrintBufferSize-3]=L'.'; + TempStr[MaxPrintBufferSize-4]=L'.'; + TempStr[MaxPrintBufferSize-5]=L'.'; + TempStr[MaxPrintBufferSize-6]=L'<'; + Print(L"%s", TempStr); + FreePool(TempStr); + } else { + Print(L"%s", Str); + } +} + +VOID PrintConfigSubString( + IN EFI_STRING ConfigString + ) +{ + EFI_STATUS Status; + if (StrStr(ConfigString, L"NAMESPACE=")) { + Print(L"\n"); + Print(L"%s\n", ConfigString); + } else if (StrStr(ConfigString, L"PATH=")) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + Status = DevicePathFromCfgString(&ConfigString[StrLen(L"PATH=")], StrLen(ConfigString) - StrLen(L"PATH="), &DevicePath); + if (!EFI_ERROR(Status)) + Print(L"%s (%s)\n", ConfigString, ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*) DevicePath, FALSE, FALSE)); + else + Print(L"%s\n", ConfigString); + FreePool(DevicePath); + } else if (StrStr(ConfigString, L"VALUE=")) { + PrintLongString(ConfigString); + Print(L"\n"); + UINT8* Buffer; + UINTN BufferSize; + ByteCfgStringToBufferReversed(&ConfigString[StrLen(L"VALUE=")], StrLen(&ConfigString[StrLen(L"VALUE=")]), &Buffer, &BufferSize); + PrintBuffer(Buffer, BufferSize); + FreePool(Buffer); + } else { + Print(L"%s\n", ConfigString); + } +} + +VOID PrintConfigString( + IN EFI_STRING ConfigString + ) +{ + UINTN StartIndex=0; + for (UINTN i=0; ConfigString[i] != 0; i++) { + if (ConfigString[i] == L'&') { + ConfigString[i] = 0; + PrintConfigSubString(&ConfigString[StartIndex]); + StartIndex = i+1; + } + } + PrintConfigSubString(&ConfigString[StartIndex]); +} + +EFI_STRING ProgressErrorStr(UINT32 ProgressErr) +{ + switch (ProgressErr) { + case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND: + return L"NamespaceId not found\n"; + case KEYWORD_HANDLER_MALFORMED_STRING: + return L"Malformed string\n"; + case KEYWORD_HANDLER_KEYWORD_NOT_FOUND: + return L"Keyword not found\n"; + case KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED: + return L"Incompatible value detected\n"; + case KEYWORD_HANDLER_ACCESS_NOT_PERMITTED: + return L"Access not permitted\n"; + default: + return L"Unknown error\n"; + } +} + +VOID Usage() +{ + Print(L"Usage:\n"); + Print(L"HIIKeyword get <NamespaceStr> <KeywordStr>\n"); + Print(L"HIIKeyword set <KeywordStr>\n"); +} + +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *gHiiConfigKeywordHandler = NULL; + EFI_STATUS Status = gBS->LocateProtocol(&gEfiConfigKeywordHandlerProtocolGuid, + NULL, + (VOID **)&gHiiConfigKeywordHandler); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't locate gEfiConfigKeywordHandlerProtocolGuid: %r", Status); + return Status; + } + + if (Argc==1) { + Usage(); + return EFI_SUCCESS; + } + + EFI_STRING Progress; + UINT32 ProgressErr; + if (!StrCmp(Argv[1], L"get")) { + if (Argc != 4) { + Print(L"Wrong argument!\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + EFI_STRING NameSpaceId = Argv[2]; + EFI_STRING KeywordString = Argv[3]; + if (!StrCmp(NameSpaceId, L'\0')) { + NameSpaceId = NULL; + } + if (!StrCmp(KeywordString, L'\0')) { + KeywordString = NULL; + } + + EFI_STRING Results; + Status = gHiiConfigKeywordHandler->GetData(gHiiConfigKeywordHandler, + NameSpaceId, + KeywordString, + &Progress, + &ProgressErr, + &Results); + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed %s\n", Progress); + } + if (ProgressErr) { + Print(L"Error! ProgressErr=%s\n", ProgressErrorStr(ProgressErr)); + } + if (EFI_ERROR(Status)) { + Print(L"Error! GetData returned %r\n", Status); + return Status; + } + Print(L"Response: "); + PrintLongString(Results); + Print(L"\n\n"); + PrintConfigString(Results); + FreePool(Results); + } else if (!StrCmp(Argv[1], L"set")) { + if (Argc != 3) { + Print(L"Wrong argument!\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + Status = gHiiConfigKeywordHandler->SetData(gHiiConfigKeywordHandler, + Argv[2], + &Progress, + &ProgressErr); + if (StrCmp(Progress, L'\0')) { + Print(L"Part of string was unparsed %s\n", Progress); + } + if (ProgressErr) { + Print(L"Error! ProgressErr=%s\n", ProgressErrorStr(ProgressErr)); + } + if (EFI_ERROR(Status)) { + Print(L"Error! SetData returned %r\n", Status); + return Status; + } + } else { + Print(L"Wrong argument!\n"); + Usage(); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/HIIKeyword/HIIKeyword.inf b/UefiLessonsPkg/HIIKeyword/HIIKeyword.inf new file mode 100644 index 0000000..de46152 --- /dev/null +++ b/UefiLessonsPkg/HIIKeyword/HIIKeyword.inf @@ -0,0 +1,24 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIKeyword + FILE_GUID = a9ec2c65-7a2b-41b8-bab0-fb4ad8ecfdde + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + HIIKeyword.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + ShellCEntryLib + UefiLib + +[Protocols] + gEfiConfigKeywordHandlerProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize + diff --git a/UefiLessonsPkg/UefiLessonsPkg.dsc b/UefiLessonsPkg/UefiLessonsPkg.dsc index 7be25fe..5397974 100644 --- a/UefiLessonsPkg/UefiLessonsPkg.dsc +++ b/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -82,6 +82,9 @@ UefiLessonsPkg/HIIFormCheckbox/HIIFormCheckbox.inf UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements.inf UefiLessonsPkg/HIIFormLabel/HIIFormLabel.inf + UefiLessonsPkg/HIIConfig/HIIConfig.inf + UefiLessonsPkg/HIIKeyword/HIIKeyword.inf + UefiLessonsPkg/HIIFormDataElementsWithKeywords/HIIFormDataElementsWithKeywords.inf UefiLessonsPkg/FfsFile/FfsFile.inf UefiLessonsPkg/SetSku/SetSku.inf |