diff options
Diffstat (limited to 'UefiLessonsPkg')
26 files changed, 2324 insertions, 2 deletions
diff --git a/UefiLessonsPkg/HIIAddLocalization/HIIAddLocalization.c b/UefiLessonsPkg/HIIAddLocalization/HIIAddLocalization.c index 71288a1..15e9261 100644 --- a/UefiLessonsPkg/HIIAddLocalization/HIIAddLocalization.c +++ b/UefiLessonsPkg/HIIAddLocalization/HIIAddLocalization.c @@ -22,12 +22,12 @@ UefiMain ( EFI_HII_HANDLE* Handle = HiiGetHiiHandles(&PackageGuid); /* *** If you add this: *** - for (UINTN i=0; i<0xFFFF; i++) { + for (UINTN i=1; i<0xFFFF; i++) { EFI_STRING String = HiiGetString(*Handle, i, "en-US"); if (String != NULL) { Print(L"ID=%d, %s\n", i, String); + FreePool(String); } - FreePool(String); } */ /* *** You would get: *** diff --git a/UefiLessonsPkg/HIIFormCallbackDebug/Data.h b/UefiLessonsPkg/HIIFormCallbackDebug/Data.h new file mode 100644 index 0000000..8df01aa --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug/Data.h @@ -0,0 +1,23 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0xf8f0d09a, 0xbc44, 0x4490, {0xb1, 0x7a, 0xdd, 0xf0, 0xe5, 0xdc, 0x41, 0x7f}} +#define DATAPATH_GUID {0xfb821964, 0xacb4, 0x437b, {0x9f, 0xe6, 0x66, 0xaa, 0x7a, 0xd7, 0xc5, 0xd8}} +#define STORAGE_GUID {0x37807592, 0x733a, 0x4f1b, {0x95, 0x57, 0xf2, 0x2a, 0xf7, 0x43, 0xe8, 0xc2}} + +#define CHECKBOX_QUESTION_ID 0x5555 +#define NUMERIC_QUESTION_ID 0x4444 + +#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]; +} VARIABLE_STRUCTURE; +#pragma pack() + +#endif diff --git a/UefiLessonsPkg/HIIFormCallbackDebug/Form.vfr b/UefiLessonsPkg/HIIFormCallbackDebug/Form.vfr new file mode 100644 index 0000000..8aed449 --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug/Form.vfr @@ -0,0 +1,109 @@ +#include <Uefi/UefiMultiPhase.h> +#include "Data.h" + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(FORMSET_TITLE), + help = STRING_TOKEN(FORMSET_HELP), + + varstore VARIABLE_STRUCTURE, + 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, + questionid = CHECKBOX_QUESTION_ID, + prompt = STRING_TOKEN(CHECKBOX_PROMPT), + help = STRING_TOKEN(CHECKBOX_HELP), + flags = INTERACTIVE, + default = TRUE, defaultstore = StandardDefault, + default = FALSE, defaultstore = ManufactureDefault, + endcheckbox; + + numeric + name = NumericQuestion, + varid = FormData.NumericValue, + questionid = NUMERIC_QUESTION_ID, + prompt = STRING_TOKEN(NUMERIC_PROMPT), + help = STRING_TOKEN(NUMERIC_HELP), + flags = NUMERIC_SIZE_2 | DISPLAY_UINT_HEX | INTERACTIVE, + //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), + flags = INTERACTIVE, + 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/HIIFormCallbackDebug/HIIFormCallbackDebug.c b/UefiLessonsPkg/HIIFormCallbackDebug/HIIFormCallbackDebug.c new file mode 100644 index 0000000..455074a --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug/HIIFormCallbackDebug.c @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> + * + * SPDX-License-Identifier: MIT + */ + +#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 <Library/UefiHiiServicesLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Library/DebugLib.h> +#include <Protocol/HiiConfigAccess.h> +#include <Protocol/HiiPopup.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_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess; +EFI_GUID StorageGuid = STORAGE_GUID; +EFI_STRING StorageName = L"FormData"; + +VARIABLE_STRUCTURE FormStorage; + + +STATIC +EFI_STATUS +EFIAPI +ExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +) +{ + EFI_INPUT_KEY Key; + do { + CreatePopUp(EFI_TEXT_ATTR(EFI_RED, EFI_BLACK), &Key, L"Extract: ", Request, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + DEBUG ((EFI_D_INFO, "ExtractConfig: Request=%s\n", Request)); + + BOOLEAN AllocatedRequest = FALSE; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((Request != NULL) && !HiiIsConfigHdrMatch(Request, &StorageGuid, StorageName)) { + return EFI_NOT_FOUND; + } + + EFI_STRING ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + EFI_STRING ConfigRequestHdr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINTN Size = (StrLen(ConfigRequestHdr) + StrLen(L"&OFFSET=0&WIDTH=") + sizeof(UINTN)*2 + 1) * sizeof(CHAR16); + ConfigRequest = AllocateZeroPool(Size); + AllocatedRequest = TRUE; + UnicodeSPrint(ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, sizeof(VARIABLE_STRUCTURE)); + FreePool(ConfigRequestHdr); + } + EFI_STATUS Status = gHiiConfigRouting->BlockToConfig(gHiiConfigRouting, + ConfigRequest, + (UINT8*)&FormStorage, + sizeof(VARIABLE_STRUCTURE), + Results, + Progress); + + if (AllocatedRequest) { + FreePool(ConfigRequest); + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr(Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen(Request); + } + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +) +{ + EFI_INPUT_KEY Key; + do { + CreatePopUp(EFI_TEXT_ATTR(EFI_RED, EFI_BLACK), &Key, L"Route: ", Configuration, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + DEBUG ((EFI_D_INFO, "RouteConfig: Configuration=%s\n", Configuration)); + + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UINTN BlockSize = sizeof(VARIABLE_STRUCTURE); + EFI_STATUS Status = gHiiConfigRouting->ConfigToBlock(gHiiConfigRouting, + Configuration, + (UINT8*)&FormStorage, + &BlockSize, + Progress); + + return Status; +} + +EFI_STRING ActionToStr(EFI_BROWSER_ACTION Action) +{ + switch (Action) { + case EFI_BROWSER_ACTION_CHANGING: + return L"EFI_BROWSER_ACTION_CHANGING"; + case EFI_BROWSER_ACTION_CHANGED: + return L"EFI_BROWSER_ACTION_CHANGED"; + case EFI_BROWSER_ACTION_RETRIEVE: + return L"EFI_BROWSER_ACTION_RETRIEVE"; + case EFI_BROWSER_ACTION_FORM_OPEN: + return L"EFI_BROWSER_ACTION_FORM_OPEN"; + case EFI_BROWSER_ACTION_FORM_CLOSE: + return L"EFI_BROWSER_ACTION_FORM_CLOSE"; + case EFI_BROWSER_ACTION_SUBMITTED: + return L"EFI_BROWSER_ACTION_SUBMITTED"; + case EFI_BROWSER_ACTION_DEFAULT_STANDARD: + return L"EFI_BROWSER_ACTION_DEFAULT_STANDARD"; + case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING: + return L"EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING"; + case EFI_BROWSER_ACTION_DEFAULT_SAFE: + return L"EFI_BROWSER_ACTION_DEFAULT_SAFE"; + case EFI_BROWSER_ACTION_DEFAULT_PLATFORM: + return L"EFI_BROWSER_ACTION_DEFAULT_PLATFORM"; + case EFI_BROWSER_ACTION_DEFAULT_HARDWARE: + return L"EFI_BROWSER_ACTION_DEFAULT_HARDWARE"; + case EFI_BROWSER_ACTION_DEFAULT_FIRMWARE: + return L"EFI_BROWSER_ACTION_DEFAULT_FIRMWARE"; + default: + return L"Unknown"; + } +} + +EFI_STRING TypeToStr(UINT8 Type) +{ + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + return L"EFI_IFR_TYPE_NUM_SIZE_8"; + case EFI_IFR_TYPE_NUM_SIZE_16: + return L"EFI_IFR_TYPE_NUM_SIZE_16"; + case EFI_IFR_TYPE_NUM_SIZE_32: + return L"EFI_IFR_TYPE_NUM_SIZE_32"; + case EFI_IFR_TYPE_NUM_SIZE_64: + return L"EFI_IFR_TYPE_NUM_SIZE_64"; + case EFI_IFR_TYPE_BOOLEAN: + return L"EFI_IFR_TYPE_BOOLEAN"; + case EFI_IFR_TYPE_TIME: + return L"EFI_IFR_TYPE_TIME"; + case EFI_IFR_TYPE_DATE: + return L"EFI_IFR_TYPE_DATE"; + case EFI_IFR_TYPE_STRING: + return L"EFI_IFR_TYPE_STRING"; + case EFI_IFR_TYPE_OTHER: + return L"EFI_IFR_TYPE_OTHER"; + case EFI_IFR_TYPE_UNDEFINED: + return L"EFI_IFR_TYPE_UNDEFINED"; + case EFI_IFR_TYPE_ACTION: + return L"EFI_IFR_TYPE_ACTION"; + case EFI_IFR_TYPE_BUFFER: + return L"EFI_IFR_TYPE_BUFFER"; + case EFI_IFR_TYPE_REF: + return L"EFI_IFR_TYPE_REF"; + default: + return L"Unknown"; + } +} + +VOID CallbackValueToStr(UINT8 Type, EFI_IFR_TYPE_VALUE *Value, EFI_STRING* ValueStr, UINTN ValueStrSize) +{ + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->u8); + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->u16); + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->u32); + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%ld", Value->u64); + break; + case EFI_IFR_TYPE_BOOLEAN: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->b); + break; + case EFI_IFR_TYPE_TIME: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%02d:%02d:%02d", Value->time.Hour, Value->time.Minute, Value->time.Second); + break; + case EFI_IFR_TYPE_DATE: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%04d/%02d/%02d", Value->date.Year, Value->date.Month, Value->date.Day); + break; + case EFI_IFR_TYPE_STRING: + if (Value->string) + UnicodeSPrint(*ValueStr, ValueStrSize, L"%s", HiiGetString(mHiiHandle, Value->string, "en-US")); + else + UnicodeSPrint(*ValueStr, ValueStrSize, L"NO STRING!"); + break; + default: + UnicodeSPrint(*ValueStr, ValueStrSize, L"Unknown"); + break; + } +} + +VOID DebugCallbackValue(UINT8 Type, EFI_IFR_TYPE_VALUE *Value) +{ + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + DEBUG ((EFI_D_INFO, "%d\n", Value->u8)); + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + DEBUG ((EFI_D_INFO, "%d\n", Value->u16)); + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + DEBUG ((EFI_D_INFO, "%d\n", Value->u32)); + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + DEBUG ((EFI_D_INFO, "%ld\n", Value->u64)); + break; + case EFI_IFR_TYPE_BOOLEAN: + DEBUG ((EFI_D_INFO, "%d\n", Value->b)); + break; + case EFI_IFR_TYPE_TIME: + DEBUG ((EFI_D_INFO, "%02d:%02d:%02d\n", Value->time.Hour, Value->time.Minute, Value->time.Second)); + break; + case EFI_IFR_TYPE_DATE: + DEBUG ((EFI_D_INFO, "%04d/%02d/%02d\n", Value->date.Year, Value->date.Month, Value->date.Day)); + break; + case EFI_IFR_TYPE_STRING: + if (Value->string) + DEBUG ((EFI_D_INFO, "%s\n", HiiGetString(mHiiHandle, Value->string, "en-US") )); + else + DEBUG ((EFI_D_INFO, "NO STRING!\n" )); + break; + default: + DEBUG ((EFI_D_INFO, "Unknown\n" )); + break; + } +} + +VOID HIIPopupCallbackInfo(EFI_BROWSER_ACTION Action, EFI_QUESTION_ID QuestionId, UINT8 Type, EFI_IFR_TYPE_VALUE* Value) +{ + EFI_STATUS Status; + EFI_HII_POPUP_PROTOCOL* HiiPopup; + EFI_HII_POPUP_SELECTION UserSelection; + Status = gBS->LocateProtocol(&gEfiHiiPopupProtocolGuid, + NULL, + (VOID **)&HiiPopup); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Error! Can't find EFI_HII_POPUP_PROTOCOL\n")); + return; + } + + UINTN Size = 300; + EFI_STRING ValueStr = AllocateZeroPool(Size); + CallbackValueToStr(Type, Value, &ValueStr, Size); + EFI_STRING PopupStr = AllocateZeroPool(Size); + UnicodeSPrint(PopupStr, Size, L"Callback:\nAction=%s\nQuestionId=0x%04x\nType=%s\nValue=%s", ActionToStr(Action), QuestionId, TypeToStr(Type), ValueStr); + FreePool(ValueStr); + HiiSetString(mHiiHandle, STRING_TOKEN(POPUP_MESSAGE), PopupStr, NULL); + Status = HiiPopup->CreatePopup(HiiPopup, + EfiHiiPopupStyleInfo, + EfiHiiPopupTypeOk, + mHiiHandle, + STRING_TOKEN(POPUP_MESSAGE), + &UserSelection + ); + FreePool(PopupStr); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Error! Can't create popup, %r\n", Status)); + return; + } +} + +VOID PopupCallbackInfo(EFI_BROWSER_ACTION Action, EFI_QUESTION_ID QuestionId, UINT8 Type, EFI_IFR_TYPE_VALUE* Value) +{ + EFI_INPUT_KEY Key; + + UINTN Size = 100; + EFI_STRING ActionStr = AllocateZeroPool(Size); + EFI_STRING QuestionIdStr = AllocateZeroPool(Size); + EFI_STRING TypeStr = AllocateZeroPool(Size); + EFI_STRING ValueStr = AllocateZeroPool(Size); + EFI_STRING ValStr = AllocateZeroPool(Size); + CallbackValueToStr(Type, Value, &ValStr, Size); + UnicodeSPrint(ActionStr, Size, L"Action=%s", ActionToStr(Action)); + UnicodeSPrint(QuestionIdStr, Size, L"QuestionId=0x%04x", QuestionId); + UnicodeSPrint(TypeStr, Size, L"Type=%s", TypeToStr(Type)); + UnicodeSPrint(ValueStr, Size, L"Value=%s", ValStr); + do { + //CreatePopUp(EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLUE), &Key, L"Callback:", ActionStr, QuestionIdStr, TypeStr, ValueStr, NULL); + CreatePopUp(EFI_TEXT_ATTR(EFI_RED, EFI_BLACK), &Key, L"Callback:", ActionStr, QuestionIdStr, TypeStr, ValueStr, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + FreePool(ActionStr); + FreePool(QuestionIdStr); + FreePool(TypeStr); + FreePool(ValueStr); + FreePool(ValStr); +} + +STATIC +EFI_STATUS +EFIAPI +Callback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN OUT EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + //DEBUG ((EFI_D_INFO, "Callback: Action=%s, QuestionId=0x%04x, Type=%s, Value=", ActionToStr(Action), QuestionId, TypeToStr(Type))); + //DebugCallbackValue(Type, Value); + + HIIPopupCallbackInfo(Action, QuestionId, Type, Value); + //PopupCallbackInfo(Action, QuestionId, Type, Value); + + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +HIIFormCallbackDebugUnload ( + EFI_HANDLE ImageHandle + ) +{ + if (mHiiHandle != NULL) + HiiRemovePackages(mHiiHandle); + + EFI_STATUS Status = gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + + return Status; +} + +EFI_STATUS +EFIAPI +HIIFormCallbackDebugEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mConfigAccess.ExtractConfig = &ExtractConfig; + mConfigAccess.RouteConfig = &RouteConfig; + mConfigAccess.Callback = &Callback; + + EFI_STATUS Status; + Status = gBS->InstallMultipleProtocolInterfaces( + &mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + mHiiHandle = HiiAddPackages( + &gEfiCallerIdGuid, + mDriverHandle, + HIIFormCallbackDebugStrings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + return EFI_OUT_OF_RESOURCES; + } + + EFI_STRING ConfigStr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINT16 DefaultId = 1; + if (!HiiSetToDefaults(ConfigStr, DefaultId)) { + Print(L"Error! Can't set default configuration #%d\n", DefaultId); + } + + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/HIIFormCallbackDebug/HIIFormCallbackDebug.inf b/UefiLessonsPkg/HIIFormCallbackDebug/HIIFormCallbackDebug.inf new file mode 100644 index 0000000..eb04cd8 --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug/HIIFormCallbackDebug.inf @@ -0,0 +1,34 @@ +## +# Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> +# +# SPDX-License-Identifier: MIT +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIFormCallbackDebug + FILE_GUID = b16ebf1f-9a61-4bdc-a940-37c19c1ae592 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HIIFormCallbackDebugEntryPoint + UNLOAD_IMAGE = HIIFormCallbackDebugUnload + +[Sources] + HIIFormCallbackDebug.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + HiiLib + DebugLib + UefiHiiServicesLib + +[Protocols] + gEfiHiiConfigAccessProtocolGuid + gEfiHiiPopupProtocolGuid diff --git a/UefiLessonsPkg/HIIFormCallbackDebug/Strings.uni b/UefiLessonsPkg/HIIFormCallbackDebug/Strings.uni new file mode 100644 index 0000000..5ce6a3e --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug/Strings.uni @@ -0,0 +1,47 @@ +// +// 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" +#string POPUP_MESSAGE #language en-US "Popup message" diff --git a/UefiLessonsPkg/HIIFormCallbackDebug2/Data.h b/UefiLessonsPkg/HIIFormCallbackDebug2/Data.h new file mode 100644 index 0000000..8df01aa --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug2/Data.h @@ -0,0 +1,23 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0xf8f0d09a, 0xbc44, 0x4490, {0xb1, 0x7a, 0xdd, 0xf0, 0xe5, 0xdc, 0x41, 0x7f}} +#define DATAPATH_GUID {0xfb821964, 0xacb4, 0x437b, {0x9f, 0xe6, 0x66, 0xaa, 0x7a, 0xd7, 0xc5, 0xd8}} +#define STORAGE_GUID {0x37807592, 0x733a, 0x4f1b, {0x95, 0x57, 0xf2, 0x2a, 0xf7, 0x43, 0xe8, 0xc2}} + +#define CHECKBOX_QUESTION_ID 0x5555 +#define NUMERIC_QUESTION_ID 0x4444 + +#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]; +} VARIABLE_STRUCTURE; +#pragma pack() + +#endif diff --git a/UefiLessonsPkg/HIIFormCallbackDebug2/Form.vfr b/UefiLessonsPkg/HIIFormCallbackDebug2/Form.vfr new file mode 100644 index 0000000..b138472 --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug2/Form.vfr @@ -0,0 +1,130 @@ +#include <Uefi/UefiMultiPhase.h> +#include "Data.h" + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(FORMSET_TITLE), + help = STRING_TOKEN(FORMSET_HELP), + + varstore VARIABLE_STRUCTURE, + 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); + + goto 2, + prompt = STRING_TOKEN(GOTO_FORM2_PROMPT), + help = STRING_TOKEN(GOTO_FORM2_HELP); + + endform; + + form + formid = 2, + title = STRING_TOKEN(FORMID2_TITLE); + + goto 3, + prompt = STRING_TOKEN(GOTO_FORM3_PROMPT), + help = STRING_TOKEN(GOTO_FORM3_HELP); + + string + name = StringQuestion, + varid = FormData.StringValue, + prompt = STRING_TOKEN(STRING_PROMPT), + help = STRING_TOKEN(STRING_HELP), + flags = INTERACTIVE, + minsize = 5, + maxsize = 10, + default = STRING_TOKEN(STRING_DEFAULT), defaultstore = StandardDefault, + default = STRING_TOKEN(STRING_PROMPT), defaultstore = ManufactureDefault, + endstring; + + endform; + + form + formid = 3, + title = STRING_TOKEN(FORMID3_TITLE); + + checkbox + varid = FormData.CheckboxValue, + questionid = CHECKBOX_QUESTION_ID, + prompt = STRING_TOKEN(CHECKBOX_PROMPT), + help = STRING_TOKEN(CHECKBOX_HELP), + flags = INTERACTIVE, + default = TRUE, defaultstore = StandardDefault, + default = FALSE, defaultstore = ManufactureDefault, + endcheckbox; + + numeric + name = NumericQuestion, + varid = FormData.NumericValue, + questionid = NUMERIC_QUESTION_ID, + prompt = STRING_TOKEN(NUMERIC_PROMPT), + help = STRING_TOKEN(NUMERIC_HELP), + flags = NUMERIC_SIZE_2 | DISPLAY_UINT_HEX | INTERACTIVE, + //minimum = 0x1234, + //maximum = 0xaa55, + minimum = 0, + maximum = 10, + step = 1, + default = 7, defaultstore = StandardDefault, + default = 8, defaultstore = ManufactureDefault, + endnumeric; + + + 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/HIIFormCallbackDebug2/HIIFormCallbackDebug2.c b/UefiLessonsPkg/HIIFormCallbackDebug2/HIIFormCallbackDebug2.c new file mode 100644 index 0000000..f70718a --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug2/HIIFormCallbackDebug2.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> + * + * SPDX-License-Identifier: MIT + */ + +#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 <Library/UefiHiiServicesLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Library/DebugLib.h> +#include <Protocol/HiiConfigAccess.h> +#include <Protocol/HiiPopup.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_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess; +EFI_GUID StorageGuid = STORAGE_GUID; +EFI_STRING StorageName = L"FormData"; + +VARIABLE_STRUCTURE FormStorage; + + +STATIC +EFI_STATUS +EFIAPI +ExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +) +{ + EFI_INPUT_KEY Key; + do { + CreatePopUp(EFI_TEXT_ATTR(EFI_RED, EFI_BLACK), &Key, L"Extract: ", Request, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + DEBUG ((EFI_D_INFO, "ExtractConfig: Request=%s\n", Request)); + + BOOLEAN AllocatedRequest = FALSE; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((Request != NULL) && !HiiIsConfigHdrMatch(Request, &StorageGuid, StorageName)) { + return EFI_NOT_FOUND; + } + + EFI_STRING ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + EFI_STRING ConfigRequestHdr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINTN Size = (StrLen(ConfigRequestHdr) + StrLen(L"&OFFSET=0&WIDTH=") + sizeof(UINTN)*2 + 1) * sizeof(CHAR16); + ConfigRequest = AllocateZeroPool(Size); + AllocatedRequest = TRUE; + UnicodeSPrint(ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, sizeof(VARIABLE_STRUCTURE)); + FreePool(ConfigRequestHdr); + } + EFI_STATUS Status = gHiiConfigRouting->BlockToConfig(gHiiConfigRouting, + ConfigRequest, + (UINT8*)&FormStorage, + sizeof(VARIABLE_STRUCTURE), + Results, + Progress); + + if (AllocatedRequest) { + FreePool(ConfigRequest); + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr(Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen(Request); + } + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +) +{ + EFI_INPUT_KEY Key; + do { + CreatePopUp(EFI_TEXT_ATTR(EFI_RED, EFI_BLACK), &Key, L"Route: ", Configuration, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + DEBUG ((EFI_D_INFO, "RouteConfig: Configuration=%s\n", Configuration)); + + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UINTN BlockSize = sizeof(VARIABLE_STRUCTURE); + EFI_STATUS Status = gHiiConfigRouting->ConfigToBlock(gHiiConfigRouting, + Configuration, + (UINT8*)&FormStorage, + &BlockSize, + Progress); + + return Status; +} + +EFI_STRING ActionToStr(EFI_BROWSER_ACTION Action) +{ + switch (Action) { + case EFI_BROWSER_ACTION_CHANGING: + return L"EFI_BROWSER_ACTION_CHANGING"; + case EFI_BROWSER_ACTION_CHANGED: + return L"EFI_BROWSER_ACTION_CHANGED"; + case EFI_BROWSER_ACTION_RETRIEVE: + return L"EFI_BROWSER_ACTION_RETRIEVE"; + case EFI_BROWSER_ACTION_FORM_OPEN: + return L"EFI_BROWSER_ACTION_FORM_OPEN"; + case EFI_BROWSER_ACTION_FORM_CLOSE: + return L"EFI_BROWSER_ACTION_FORM_CLOSE"; + case EFI_BROWSER_ACTION_SUBMITTED: + return L"EFI_BROWSER_ACTION_SUBMITTED"; + case EFI_BROWSER_ACTION_DEFAULT_STANDARD: + return L"EFI_BROWSER_ACTION_DEFAULT_STANDARD"; + case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING: + return L"EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING"; + case EFI_BROWSER_ACTION_DEFAULT_SAFE: + return L"EFI_BROWSER_ACTION_DEFAULT_SAFE"; + case EFI_BROWSER_ACTION_DEFAULT_PLATFORM: + return L"EFI_BROWSER_ACTION_DEFAULT_PLATFORM"; + case EFI_BROWSER_ACTION_DEFAULT_HARDWARE: + return L"EFI_BROWSER_ACTION_DEFAULT_HARDWARE"; + case EFI_BROWSER_ACTION_DEFAULT_FIRMWARE: + return L"EFI_BROWSER_ACTION_DEFAULT_FIRMWARE"; + default: + return L"Unknown"; + } +} + +EFI_STRING TypeToStr(UINT8 Type) +{ + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + return L"EFI_IFR_TYPE_NUM_SIZE_8"; + case EFI_IFR_TYPE_NUM_SIZE_16: + return L"EFI_IFR_TYPE_NUM_SIZE_16"; + case EFI_IFR_TYPE_NUM_SIZE_32: + return L"EFI_IFR_TYPE_NUM_SIZE_32"; + case EFI_IFR_TYPE_NUM_SIZE_64: + return L"EFI_IFR_TYPE_NUM_SIZE_64"; + case EFI_IFR_TYPE_BOOLEAN: + return L"EFI_IFR_TYPE_BOOLEAN"; + case EFI_IFR_TYPE_TIME: + return L"EFI_IFR_TYPE_TIME"; + case EFI_IFR_TYPE_DATE: + return L"EFI_IFR_TYPE_DATE"; + case EFI_IFR_TYPE_STRING: + return L"EFI_IFR_TYPE_STRING"; + case EFI_IFR_TYPE_OTHER: + return L"EFI_IFR_TYPE_OTHER"; + case EFI_IFR_TYPE_UNDEFINED: + return L"EFI_IFR_TYPE_UNDEFINED"; + case EFI_IFR_TYPE_ACTION: + return L"EFI_IFR_TYPE_ACTION"; + case EFI_IFR_TYPE_BUFFER: + return L"EFI_IFR_TYPE_BUFFER"; + case EFI_IFR_TYPE_REF: + return L"EFI_IFR_TYPE_REF"; + default: + return L"Unknown"; + } +} + +VOID CallbackValueToStr(UINT8 Type, EFI_IFR_TYPE_VALUE *Value, EFI_STRING* ValueStr, UINTN ValueStrSize) +{ + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->u8); + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->u16); + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->u32); + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%ld", Value->u64); + break; + case EFI_IFR_TYPE_BOOLEAN: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%d", Value->b); + break; + case EFI_IFR_TYPE_TIME: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%02d:%02d:%02d", Value->time.Hour, Value->time.Minute, Value->time.Second); + break; + case EFI_IFR_TYPE_DATE: + UnicodeSPrint(*ValueStr, ValueStrSize, L"%04d/%02d/%02d", Value->date.Year, Value->date.Month, Value->date.Day); + break; + case EFI_IFR_TYPE_STRING: + if (Value->string) + UnicodeSPrint(*ValueStr, ValueStrSize, L"%s", HiiGetString(mHiiHandle, Value->string, "en-US")); + else + UnicodeSPrint(*ValueStr, ValueStrSize, L"NO STRING!"); + break; + default: + UnicodeSPrint(*ValueStr, ValueStrSize, L"Unknown"); + break; + } +} + +VOID DebugCallbackValue(UINT8 Type, EFI_IFR_TYPE_VALUE *Value) +{ + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + DEBUG ((EFI_D_INFO, "%d\n", Value->u8)); + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + DEBUG ((EFI_D_INFO, "%d\n", Value->u16)); + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + DEBUG ((EFI_D_INFO, "%d\n", Value->u32)); + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + DEBUG ((EFI_D_INFO, "%ld\n", Value->u64)); + break; + case EFI_IFR_TYPE_BOOLEAN: + DEBUG ((EFI_D_INFO, "%d\n", Value->b)); + break; + case EFI_IFR_TYPE_TIME: + DEBUG ((EFI_D_INFO, "%02d:%02d:%02d\n", Value->time.Hour, Value->time.Minute, Value->time.Second)); + break; + case EFI_IFR_TYPE_DATE: + DEBUG ((EFI_D_INFO, "%04d/%02d/%02d\n", Value->date.Year, Value->date.Month, Value->date.Day)); + break; + case EFI_IFR_TYPE_STRING: + if (Value->string) + DEBUG ((EFI_D_INFO, "%s\n", HiiGetString(mHiiHandle, Value->string, "en-US") )); + else + DEBUG ((EFI_D_INFO, "NO STRING!\n" )); + break; + default: + DEBUG ((EFI_D_INFO, "Unknown\n" )); + break; + } +} + +VOID HIIPopupCallbackInfo(EFI_BROWSER_ACTION Action, EFI_QUESTION_ID QuestionId, UINT8 Type, EFI_IFR_TYPE_VALUE* Value) +{ + EFI_STATUS Status; + EFI_HII_POPUP_PROTOCOL* HiiPopup; + EFI_HII_POPUP_SELECTION UserSelection; + Status = gBS->LocateProtocol(&gEfiHiiPopupProtocolGuid, + NULL, + (VOID **)&HiiPopup); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Error! Can't find EFI_HII_POPUP_PROTOCOL\n")); + return; + } + + UINTN Size = 300; + EFI_STRING ValueStr = AllocateZeroPool(Size); + CallbackValueToStr(Type, Value, &ValueStr, Size); + EFI_STRING PopupStr = AllocateZeroPool(Size); + UnicodeSPrint(PopupStr, Size, L"Callback:\nAction=%s\nQuestionId=0x%04x\nType=%s\nValue=%s", ActionToStr(Action), QuestionId, TypeToStr(Type), ValueStr); + FreePool(ValueStr); + HiiSetString(mHiiHandle, STRING_TOKEN(POPUP_MESSAGE), PopupStr, NULL); + Status = HiiPopup->CreatePopup(HiiPopup, + EfiHiiPopupStyleInfo, + EfiHiiPopupTypeOk, + mHiiHandle, + STRING_TOKEN(POPUP_MESSAGE), + &UserSelection + ); + FreePool(PopupStr); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Error! Can't create popup, %r\n", Status)); + return; + } +} + +VOID PopupCallbackInfo(EFI_BROWSER_ACTION Action, EFI_QUESTION_ID QuestionId, UINT8 Type, EFI_IFR_TYPE_VALUE* Value) +{ + EFI_INPUT_KEY Key; + + UINTN Size = 100; + EFI_STRING ActionStr = AllocateZeroPool(Size); + EFI_STRING QuestionIdStr = AllocateZeroPool(Size); + EFI_STRING TypeStr = AllocateZeroPool(Size); + EFI_STRING ValueStr = AllocateZeroPool(Size); + EFI_STRING ValStr = AllocateZeroPool(Size); + CallbackValueToStr(Type, Value, &ValStr, Size); + UnicodeSPrint(ActionStr, Size, L"Action=%s", ActionToStr(Action)); + UnicodeSPrint(QuestionIdStr, Size, L"QuestionId=0x%04x", QuestionId); + UnicodeSPrint(TypeStr, Size, L"Type=%s", TypeToStr(Type)); + UnicodeSPrint(ValueStr, Size, L"Value=%s", ValStr); + do { + //CreatePopUp(EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLUE), &Key, L"Callback:", ActionStr, QuestionIdStr, TypeStr, ValueStr, NULL); + CreatePopUp(EFI_TEXT_ATTR(EFI_RED, EFI_BLACK), &Key, L"Callback:", ActionStr, QuestionIdStr, TypeStr, ValueStr, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + FreePool(ActionStr); + FreePool(QuestionIdStr); + FreePool(TypeStr); + FreePool(ValueStr); + FreePool(ValStr); +} + +STATIC +EFI_STATUS +EFIAPI +Callback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN OUT EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + //DEBUG ((EFI_D_INFO, "Callback: Action=%s, QuestionId=0x%04x, Type=%s, Value=", ActionToStr(Action), QuestionId, TypeToStr(Type))); + //DebugCallbackValue(Type, Value); + + HIIPopupCallbackInfo(Action, QuestionId, Type, Value); + //PopupCallbackInfo(Action, QuestionId, Type, Value); + + if ((QuestionId == NUMERIC_QUESTION_ID) && (Action == EFI_BROWSER_ACTION_CHANGED)) { + if ((Value->u16 >= 0) && (Value->u16 <= 9)) { + *ActionRequest = Value->u16; + return EFI_SUCCESS; + } + } + + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +HIIFormCallbackDebug2Unload ( + EFI_HANDLE ImageHandle + ) +{ + if (mHiiHandle != NULL) + HiiRemovePackages(mHiiHandle); + + EFI_STATUS Status = gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + + return Status; +} + +EFI_STATUS +EFIAPI +HIIFormCallbackDebug2EntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mConfigAccess.ExtractConfig = &ExtractConfig; + mConfigAccess.RouteConfig = &RouteConfig; + mConfigAccess.Callback = &Callback; + + EFI_STATUS Status; + Status = gBS->InstallMultipleProtocolInterfaces( + &mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + mHiiHandle = HiiAddPackages( + &gEfiCallerIdGuid, + mDriverHandle, + HIIFormCallbackDebug2Strings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + return EFI_OUT_OF_RESOURCES; + } + + EFI_STRING ConfigStr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINT16 DefaultId = 1; + if (!HiiSetToDefaults(ConfigStr, DefaultId)) { + Print(L"Error! Can't set default configuration #%d\n", DefaultId); + } + + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/HIIFormCallbackDebug2/HIIFormCallbackDebug2.inf b/UefiLessonsPkg/HIIFormCallbackDebug2/HIIFormCallbackDebug2.inf new file mode 100644 index 0000000..1b363d5 --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug2/HIIFormCallbackDebug2.inf @@ -0,0 +1,34 @@ +## +# Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> +# +# SPDX-License-Identifier: MIT +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HIIFormCallbackDebug2 + FILE_GUID = 67ca8db1-ff6e-4d3f-b503-113791c9008d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HIIFormCallbackDebug2EntryPoint + UNLOAD_IMAGE = HIIFormCallbackDebug2Unload + +[Sources] + HIIFormCallbackDebug2.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + HiiLib + DebugLib + UefiHiiServicesLib + +[Protocols] + gEfiHiiConfigAccessProtocolGuid + gEfiHiiPopupProtocolGuid diff --git a/UefiLessonsPkg/HIIFormCallbackDebug2/Strings.uni b/UefiLessonsPkg/HIIFormCallbackDebug2/Strings.uni new file mode 100644 index 0000000..9b2142d --- /dev/null +++ b/UefiLessonsPkg/HIIFormCallbackDebug2/Strings.uni @@ -0,0 +1,54 @@ +// +// 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 "Form 1" +#string FORMID2_TITLE #language en-US "Form 2" +#string FORMID3_TITLE #language en-US "Form 3" +#string GOTO_FORM2_PROMPT #language en-US "Enter Form 2" +#string GOTO_FORM2_HELP #language en-US "Enter Form 2" +#string GOTO_FORM3_PROMPT #language en-US "Enter Form 3" +#string GOTO_FORM3_HELP #language en-US "Enter Form 3" + +#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" +#string POPUP_MESSAGE #language en-US "Popup message" diff --git a/UefiLessonsPkg/PasswordForm/Data.h b/UefiLessonsPkg/PasswordForm/Data.h new file mode 100644 index 0000000..75a2101 --- /dev/null +++ b/UefiLessonsPkg/PasswordForm/Data.h @@ -0,0 +1,20 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0xe54b953d, 0x7ddc, 0x455c, {0x8c, 0x1a, 0x59, 0x92, 0xbb, 0xc7, 0x72, 0xc4}} +#define DATAPATH_GUID {0xb289cf9f, 0xf911, 0x41fd, {0x9b, 0xad, 0x2c, 0x92, 0x57, 0x68, 0x86, 0x64}} +#define STORAGE_GUID {0xe7f2d73c, 0x699a, 0x4606, {0x92, 0xb6, 0xa3, 0x5e, 0x49, 0x27, 0xc4, 0xd4}} + +#define PASSWORD_MIN_LEN 6 +#define PASSWORD_MAX_LEN 8 +#define PASSWORD_STORAGE_SIZE 9 + +#define KEY_PASSWORD 0x1234 + +#pragma pack(1) +typedef struct { + CHAR16 Password[PASSWORD_STORAGE_SIZE]; +} VARIABLE_STRUCTURE; +#pragma pack() + +#endif diff --git a/UefiLessonsPkg/PasswordForm/Form.vfr b/UefiLessonsPkg/PasswordForm/Form.vfr new file mode 100644 index 0000000..10c1d1f --- /dev/null +++ b/UefiLessonsPkg/PasswordForm/Form.vfr @@ -0,0 +1,31 @@ +#include <Uefi/UefiMultiPhase.h> +#include "Data.h" + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(FORMSET_TITLE), + help = STRING_TOKEN(FORMSET_HELP), + + varstore VARIABLE_STRUCTURE, + name = FormData, + guid = STORAGE_GUID; + + defaultstore StandardDefault, + prompt = STRING_TOKEN(STANDARD_DEFAULT_PROMPT), + attribute = 0x0000; + + form + formid = 1, + title = STRING_TOKEN(FORMID1_TITLE); + + password + varid = FormData.Password, + prompt = STRING_TOKEN(PASSWORD_PROMPT), + help = STRING_TOKEN(PASSWORD_HELP), + flags = INTERACTIVE, + key = KEY_PASSWORD, + minsize = PASSWORD_MIN_LEN, + maxsize = PASSWORD_MAX_LEN, + endpassword; + endform; +endformset; diff --git a/UefiLessonsPkg/PasswordForm/PasswordForm.c b/UefiLessonsPkg/PasswordForm/PasswordForm.c new file mode 100644 index 0000000..08ac245 --- /dev/null +++ b/UefiLessonsPkg/PasswordForm/PasswordForm.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> + * + * SPDX-License-Identifier: MIT + */ + +#include <Library/BaseMemoryLib.h> +#include <Library/DevicePathLib.h> +#include <Library/HiiLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiHiiServicesLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Protocol/HiiConfigAccess.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_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess; +EFI_GUID StorageGuid = STORAGE_GUID; +EFI_STRING StorageName = L"FormData"; + +VARIABLE_STRUCTURE FormStorage; + + +STATIC +EFI_STATUS +EFIAPI +ExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +) +{ + BOOLEAN AllocatedRequest = FALSE; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((Request != NULL) && !HiiIsConfigHdrMatch(Request, &StorageGuid, StorageName)) { + return EFI_NOT_FOUND; + } + + EFI_STRING ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + EFI_STRING ConfigRequestHdr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINTN Size = (StrLen(ConfigRequestHdr) + StrLen(L"&OFFSET=0&WIDTH=") + sizeof(UINTN)*2 + 1) * sizeof(CHAR16); + ConfigRequest = AllocateZeroPool(Size); + AllocatedRequest = TRUE; + UnicodeSPrint(ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, sizeof(VARIABLE_STRUCTURE)); + FreePool(ConfigRequestHdr); + } + EFI_STATUS Status = gHiiConfigRouting->BlockToConfig(gHiiConfigRouting, + ConfigRequest, + (UINT8*)&FormStorage, + sizeof(VARIABLE_STRUCTURE), + Results, + Progress); + + if (AllocatedRequest) { + FreePool(ConfigRequest); + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr(Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen(Request); + } + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UINTN BlockSize = sizeof(VARIABLE_STRUCTURE); + EFI_STATUS Status = gHiiConfigRouting->ConfigToBlock(gHiiConfigRouting, + Configuration, + (UINT8*)&FormStorage, + &BlockSize, + Progress); + + return Status; +} + +BOOLEAN OldPasswordVerified = FALSE; + +EFI_STATUS HandlePasswordInput(EFI_STRING Password) +{ + if (Password[0] == 0) { + // Form Browser checks if password exists + if (FormStorage.Password[0] != 0) { + return EFI_ALREADY_STARTED; + } else { + return EFI_SUCCESS; + } + } else { + // Form Browser sends password value + // It can be old password to check or initial/updated password to set + + if (FormStorage.Password[0] == 0) { + // Set initial password + StrnCpyS(FormStorage.Password, PASSWORD_STORAGE_SIZE, Password, StrLen(Password)); + return EFI_SUCCESS; + } + + if (!OldPasswordVerified) { + // Check old password + if (StrCmp(Password, FormStorage.Password)) + return EFI_NOT_READY; + + OldPasswordVerified = TRUE; + return EFI_SUCCESS; + } + + // Update password + StrnCpyS(FormStorage.Password, PASSWORD_STORAGE_SIZE, Password, StrLen(Password)); + OldPasswordVerified = FALSE; + return EFI_SUCCESS; + } +} + +STATIC +EFI_STATUS +EFIAPI +Callback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN OUT EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + if ((QuestionId == KEY_PASSWORD) && (Action == EFI_BROWSER_ACTION_CHANGING)) { + if (Value->string == 0) { + return EFI_UNSUPPORTED; + } + + EFI_STRING Password = HiiGetString(mHiiHandle, Value->string, "en-US"); + Status = HandlePasswordInput(Password); + FreePool(Password); + return Status; + } + + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +PasswordFormUnload ( + EFI_HANDLE ImageHandle + ) +{ + if (mHiiHandle != NULL) + HiiRemovePackages(mHiiHandle); + + EFI_STATUS Status = gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + + return Status; +} + +EFI_STATUS +EFIAPI +PasswordFormEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mConfigAccess.ExtractConfig = &ExtractConfig; + mConfigAccess.RouteConfig = &RouteConfig; + mConfigAccess.Callback = &Callback; + + EFI_STATUS Status; + Status = gBS->InstallMultipleProtocolInterfaces( + &mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + mHiiHandle = HiiAddPackages( + &gEfiCallerIdGuid, + mDriverHandle, + PasswordFormStrings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + return EFI_OUT_OF_RESOURCES; + } + + EFI_STRING ConfigStr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINT16 DefaultId = 0; + if (!HiiSetToDefaults(ConfigStr, DefaultId)) { + Print(L"Error! Can't set default configuration #%d\n", DefaultId); + } + + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/PasswordForm/PasswordForm.inf b/UefiLessonsPkg/PasswordForm/PasswordForm.inf new file mode 100644 index 0000000..28379d7 --- /dev/null +++ b/UefiLessonsPkg/PasswordForm/PasswordForm.inf @@ -0,0 +1,32 @@ +## +# Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> +# +# SPDX-License-Identifier: MIT +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = PasswordForm + FILE_GUID = 3d84c3d8-cdca-4a9c-8aa4-b637bc885f5e + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PasswordFormEntryPoint + UNLOAD_IMAGE = PasswordFormUnload + +[Sources] + PasswordForm.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + UefiHiiServicesLib + HiiLib + +[Protocols] + gEfiHiiConfigAccessProtocolGuid diff --git a/UefiLessonsPkg/PasswordForm/Strings.uni b/UefiLessonsPkg/PasswordForm/Strings.uni new file mode 100644 index 0000000..b2dfd34 --- /dev/null +++ b/UefiLessonsPkg/PasswordForm/Strings.uni @@ -0,0 +1,16 @@ +// +// Copyright (c) 2024, 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 STANDARD_DEFAULT_PROMPT #language en-US "Standard default" +#string MFG_DEFAULT_PROMPT #language en-US "Manufacture default" +#string PASSWORD_PROMPT #language en-US "Password prompt" +#string PASSWORD_HELP #language en-US "Password help" +#string PASSWORD_DEFAULT #language en-US "123456" diff --git a/UefiLessonsPkg/PasswordFormWithHash/Data.h b/UefiLessonsPkg/PasswordFormWithHash/Data.h new file mode 100644 index 0000000..a83476d --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/Data.h @@ -0,0 +1,20 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0xe54b953d, 0x7ddc, 0x455c, {0x8c, 0x1a, 0x59, 0x92, 0xbb, 0xc7, 0x72, 0xc4}} +#define DATAPATH_GUID {0xb289cf9f, 0xf911, 0x41fd, {0x9b, 0xad, 0x2c, 0x92, 0x57, 0x68, 0x86, 0x64}} +#define STORAGE_GUID {0xe7f2d73c, 0x699a, 0x4606, {0x92, 0xb6, 0xa3, 0x5e, 0x49, 0x27, 0xc4, 0xd4}} + +#define PASSWORD_MIN_LEN 6 +#define PASSWORD_MAX_LEN 8 +#define HASHED_PASSWORD_SIZE 64 + +#define KEY_PASSWORD 0x1234 + +#pragma pack(1) +typedef struct { + UINT8 Password[HASHED_PASSWORD_SIZE]; +} VARIABLE_STRUCTURE; +#pragma pack() + +#endif diff --git a/UefiLessonsPkg/PasswordFormWithHash/Form.vfr b/UefiLessonsPkg/PasswordFormWithHash/Form.vfr new file mode 100644 index 0000000..10c1d1f --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/Form.vfr @@ -0,0 +1,31 @@ +#include <Uefi/UefiMultiPhase.h> +#include "Data.h" + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(FORMSET_TITLE), + help = STRING_TOKEN(FORMSET_HELP), + + varstore VARIABLE_STRUCTURE, + name = FormData, + guid = STORAGE_GUID; + + defaultstore StandardDefault, + prompt = STRING_TOKEN(STANDARD_DEFAULT_PROMPT), + attribute = 0x0000; + + form + formid = 1, + title = STRING_TOKEN(FORMID1_TITLE); + + password + varid = FormData.Password, + prompt = STRING_TOKEN(PASSWORD_PROMPT), + help = STRING_TOKEN(PASSWORD_HELP), + flags = INTERACTIVE, + key = KEY_PASSWORD, + minsize = PASSWORD_MIN_LEN, + maxsize = PASSWORD_MAX_LEN, + endpassword; + endform; +endformset; diff --git a/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.c b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.c new file mode 100644 index 0000000..04457c6 --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> + * + * SPDX-License-Identifier: MIT + */ + +#include <Library/BaseMemoryLib.h> +#include <Library/DevicePathLib.h> +#include <Library/HiiLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiHiiServicesLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Protocol/HiiConfigAccess.h> +#include <Protocol/Hash2.h> +#include <Protocol/ServiceBinding.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_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess; +EFI_GUID StorageGuid = STORAGE_GUID; +EFI_STRING StorageName = L"FormData"; + +VARIABLE_STRUCTURE FormStorage; + +EFI_SERVICE_BINDING_PROTOCOL* hash2ServiceBinding; +EFI_HASH2_PROTOCOL* hash2Protocol; +EFI_HANDLE hash2ChildHandle = NULL; + +STATIC +EFI_STATUS +EFIAPI +ExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +) +{ + BOOLEAN AllocatedRequest = FALSE; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((Request != NULL) && !HiiIsConfigHdrMatch(Request, &StorageGuid, StorageName)) { + return EFI_NOT_FOUND; + } + + EFI_STRING ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + EFI_STRING ConfigRequestHdr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINTN Size = (StrLen(ConfigRequestHdr) + StrLen(L"&OFFSET=0&WIDTH=") + sizeof(UINTN)*2 + 1) * sizeof(CHAR16); + ConfigRequest = AllocateZeroPool(Size); + AllocatedRequest = TRUE; + UnicodeSPrint(ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, sizeof(VARIABLE_STRUCTURE)); + FreePool(ConfigRequestHdr); + } + EFI_STATUS Status = gHiiConfigRouting->BlockToConfig(gHiiConfigRouting, + ConfigRequest, + (UINT8*)&FormStorage, + sizeof(VARIABLE_STRUCTURE), + Results, + Progress); + + if (AllocatedRequest) { + FreePool(ConfigRequest); + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr(Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen(Request); + } + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UINTN BlockSize = sizeof(VARIABLE_STRUCTURE); + EFI_STATUS Status = gHiiConfigRouting->ConfigToBlock(gHiiConfigRouting, + Configuration, + (UINT8*)&FormStorage, + &BlockSize, + Progress); + + return Status; +} + +BOOLEAN OldPasswordVerified = FALSE; + +EFI_STATUS ComputeStringHash(EFI_STRING Password, UINT8* HashedPassword) +{ + EFI_GUID HashGuid = EFI_HASH_ALGORITHM_SHA512_GUID; + EFI_HASH2_OUTPUT Hash; + EFI_STATUS Status = hash2Protocol->Hash(hash2Protocol, + &HashGuid, + (UINT8*)Password, + StrLen(Password)*sizeof(CHAR16), + &Hash); + if (EFI_ERROR(Status)) { + return Status; + } + CopyMem(HashedPassword, Hash.Sha512Hash, HASHED_PASSWORD_SIZE); + return EFI_SUCCESS; +} + +EFI_STATUS HandlePasswordInput(EFI_STRING Password) +{ + EFI_STATUS Status; + + if (Password[0] == 0) { + // Form Browser checks if password exists + if (FormStorage.Password[0] != 0) { + return EFI_ALREADY_STARTED; + } else { + return EFI_SUCCESS; + } + } else { + // Form Browser sends password value + // It can be old password to check or initial/updated password to set + + if (FormStorage.Password[0] == 0) { + // Set initial password + ComputeStringHash(Password, FormStorage.Password); + if (EFI_ERROR(Status)) { + return Status; + } + return EFI_SUCCESS; + } + + if (!OldPasswordVerified) { + // Check old password + UINT8 TempHash[HASHED_PASSWORD_SIZE]; + ComputeStringHash(Password, TempHash); + if (CompareMem(TempHash, FormStorage.Password, HASHED_PASSWORD_SIZE)) + return EFI_NOT_READY; + + OldPasswordVerified = TRUE; + return EFI_SUCCESS; + } + + // Update password + Status = ComputeStringHash(Password, FormStorage.Password); + if (EFI_ERROR(Status)) { + return Status; + } + OldPasswordVerified = FALSE; + return EFI_SUCCESS; + } +} + +STATIC +EFI_STATUS +EFIAPI +Callback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN OUT EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + if ((QuestionId == KEY_PASSWORD) && (Action == EFI_BROWSER_ACTION_CHANGING)) { + if (Value->string == 0) { + return EFI_UNSUPPORTED; + } + + EFI_STRING Password = HiiGetString(mHiiHandle, Value->string, "en-US"); + Status = HandlePasswordInput(Password); + FreePool(Password); + return Status; + } + + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +PasswordFormWithHashUnload ( + EFI_HANDLE ImageHandle + ) +{ + hash2ServiceBinding->DestroyChild(hash2ServiceBinding, hash2ChildHandle); + + if (mHiiHandle != NULL) + HiiRemovePackages(mHiiHandle); + + EFI_STATUS Status = gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + + return Status; +} + +EFI_STATUS +EFIAPI +PasswordFormWithHashEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + Status = gBS->LocateProtocol(&gEfiHash2ServiceBindingProtocolGuid, + NULL, + (VOID **)&hash2ServiceBinding); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't locate gEfiHash2ServiceBindingProtocolGuid: %r\n", Status); + return Status; + } + + Status = hash2ServiceBinding->CreateChild(hash2ServiceBinding, + &hash2ChildHandle); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't create child on gEfiHash2ServiceBindingProtocolGuid: %r\n", Status); + return Status; + } + + Status = gBS->OpenProtocol(hash2ChildHandle, + &gEfiHash2ProtocolGuid, + (VOID **)&hash2Protocol, + NULL, + hash2ChildHandle, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't open gEfiHashProtocolGuid: %r\n", Status); + return Status; + } + + mConfigAccess.ExtractConfig = &ExtractConfig; + mConfigAccess.RouteConfig = &RouteConfig; + mConfigAccess.Callback = &Callback; + + Status = gBS->InstallMultipleProtocolInterfaces( + &mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + mHiiHandle = HiiAddPackages( + &gEfiCallerIdGuid, + mDriverHandle, + PasswordFormWithHashStrings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + return EFI_OUT_OF_RESOURCES; + } + + EFI_STRING ConfigStr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINT16 DefaultId = 0; + if (!HiiSetToDefaults(ConfigStr, DefaultId)) { + Print(L"Error! Can't set default configuration #%d\n", DefaultId); + } + + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf new file mode 100644 index 0000000..02674b4 --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf @@ -0,0 +1,34 @@ +## +# Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> +# +# SPDX-License-Identifier: MIT +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = PasswordFormWithHash + FILE_GUID = 6dfb156a-ec61-47d2-841b-f739084add1d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PasswordFormWithHashEntryPoint + UNLOAD_IMAGE = PasswordFormWithHashUnload + +[Sources] + PasswordFormWithHash.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + UefiHiiServicesLib + HiiLib + +[Protocols] + gEfiHiiConfigAccessProtocolGuid + gEfiHash2ServiceBindingProtocolGuid + gEfiHash2ProtocolGuid diff --git a/UefiLessonsPkg/PasswordFormWithHash/Strings.uni b/UefiLessonsPkg/PasswordFormWithHash/Strings.uni new file mode 100644 index 0000000..5cd0ca1 --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/Strings.uni @@ -0,0 +1,15 @@ +// +// Copyright (c) 2024, 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 STANDARD_DEFAULT_PROMPT #language en-US "Standard default" +#string MFG_DEFAULT_PROMPT #language en-US "Manufacture default" +#string PASSWORD_PROMPT #language en-US "Password prompt" +#string PASSWORD_HELP #language en-US "Password help" diff --git a/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.c b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.c new file mode 100644 index 0000000..02ed0f9 --- /dev/null +++ b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> + * + * SPDX-License-Identifier: MIT + */ + +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include <Protocol/SimpleClass.h> + +EFI_EVENT Event; +STATIC VOID *mRegistrationTracker; +UINTN NotifyData = 0; + +VOID EFIAPI NotifyFunc(EFI_EVENT Event, VOID* Context) +{ + if (Context == NULL) + return; + + Print(L"\nEvent is signaled! Context = %d\n", *(UINTN*)Context); + *(UINTN*)Context += 1; + + SIMPLE_CLASS_PROTOCOL* SimpleClass; + EFI_STATUS Status; + Status = gBS->LocateProtocol(&gSimpleClassProtocolGuid, + // NULL, + mRegistrationTracker, + (VOID**)&SimpleClass); + if (EFI_ERROR(Status)) { + Print(L"Error! LocateProtocol returned: %r\n", Status); + return; + } + + UINTN Number; + Status = SimpleClass->GetNumber(&Number); + if (!EFI_ERROR(Status)) { + Print(L"Current number = %d\n", Number); + } else { + Print(L"Error! Can't get number: %r\n", Status); + return; + } + + Status = SimpleClass->SetNumber(Number+5); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't set number: %r\n", Status); + return; + } +} + + +EFI_STATUS +EFIAPI +ProtocolEventDriverUnload ( + EFI_HANDLE ImageHandle + ) +{ + gBS->CloseEvent(Event); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ProtocolEventDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + + Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + &NotifyFunc, + &NotifyData, + &Event); + if (EFI_ERROR(Status)) { + Print(L"Error! CreateEvent returned: %r\n", Status); + return Status; + } + + Status = gBS->RegisterProtocolNotify(&gSimpleClassProtocolGuid, + Event, + &mRegistrationTracker); + if (EFI_ERROR(Status)) { + Print(L"Error! RegisterProtocolNotify returned: %r\n", Status); + return Status; + } + +/* + Event = EfiCreateProtocolNotifyEvent(&gSimpleClassProtocolGuid, + TPL_NOTIFY, + &NotifyFunc, + &NotifyData, + &mRegistrationTracker); +*/ + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf new file mode 100644 index 0000000..b05651f --- /dev/null +++ b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf @@ -0,0 +1,28 @@ +## +# Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> +# +# SPDX-License-Identifier: MIT +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ProtocolEventDriver + FILE_GUID = 0b59d62a-3250-42eb-9859-364faf5bc9c8 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = ProtocolEventDriverEntryPoint + UNLOAD_IMAGE = ProtocolEventDriverUnload + +[Sources] + ProtocolEventDriver.c + +[Packages] + MdePkg/MdePkg.dec + UefiLessonsPkg/UefiLessonsPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + +[Protocols] + gSimpleClassProtocolGuid diff --git a/UefiLessonsPkg/ShowStrings/ShowStrings.c b/UefiLessonsPkg/ShowStrings/ShowStrings.c new file mode 100644 index 0000000..00d0625 --- /dev/null +++ b/UefiLessonsPkg/ShowStrings/ShowStrings.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> + * + * SPDX-License-Identifier: MIT + */ + +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/HiiLib.h> +#include <Library/MemoryAllocationLib.h> + + +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + if (Argc != 2) { + Print(L"Usage:\n"); + Print(L" ShowStrings [Package GUID]\n"); + return EFI_INVALID_PARAMETER; + } + + EFI_GUID PackageGuid; + EFI_STATUS Status = StrToGuid(Argv[1], &PackageGuid); + if (Status != RETURN_SUCCESS) { + Print(L"Error! Can't convert <Package GUID> argument to GUID\n"); + return EFI_INVALID_PARAMETER; + } + + EFI_HII_HANDLE* Handle = HiiGetHiiHandles(&PackageGuid); + + for (UINTN i=1; i<0xFFFF; i++) { + EFI_STRING String = HiiGetString(*Handle, i, "en-US"); + if (String != NULL) { + Print(L"ID=%d, %s\n", i, String); + FreePool(String); + } + } + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/ShowStrings/ShowStrings.inf b/UefiLessonsPkg/ShowStrings/ShowStrings.inf new file mode 100644 index 0000000..c5e8206 --- /dev/null +++ b/UefiLessonsPkg/ShowStrings/ShowStrings.inf @@ -0,0 +1,25 @@ +## +# Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com> +# +# SPDX-License-Identifier: MIT +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ShowStrings + FILE_GUID = ae4c1ff2-5621-4e53-a5f8-e4652b457661 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + ShowStrings.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + ShellCEntryLib + UefiLib + HiiLib diff --git a/UefiLessonsPkg/UefiLessonsPkg.dsc b/UefiLessonsPkg/UefiLessonsPkg.dsc index d0cc2df..c5698ca 100644 --- a/UefiLessonsPkg/UefiLessonsPkg.dsc +++ b/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -93,6 +93,12 @@ UefiLessonsPkg/SetSku/SetSku.inf UefiLessonsPkg/HiddenSettings/HiddenSettings.inf UefiLessonsPkg/ShowHIIext/ShowHIIext.inf + UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf + UefiLessonsPkg/ShowStrings/ShowStrings.inf + UefiLessonsPkg/PasswordForm/PasswordForm.inf + UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf + UefiLessonsPkg/HIIFormCallbackDebug/HIIFormCallbackDebug.inf + UefiLessonsPkg/HIIFormCallbackDebug2/HIIFormCallbackDebug2.inf #[PcdsFixedAtBuild] # gUefiLessonsPkgTokenSpaceGuid.PcdInt8|0x88|UINT8|0x3B81CDF1 |