From c16c5ce441b6c88734458ffa1e223f66402b4d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Tue, 24 Jun 2025 15:29:06 +0200 Subject: [PATCH 01/15] DasharoModulePkg: Add Sovereign Boot Wizard application MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../SovereignBootWizard/BootOptionParsing.c | 468 +++++++++++ .../SovereignBootWizard/SovereignBootWizard.c | 744 ++++++++++++++++++ .../SovereignBootWizard/SovereignBootWizard.h | 180 +++++ .../SovereignBootWizard.inf | 81 ++ .../SovereignBootWizard.uni | 15 + .../SovereignBootWizardExtra.uni | 12 + .../SovereignBootWizardHii.h | 92 +++ .../SovereignBootWizardVfr.vfr | 161 ++++ .../SovereignBootWizardVfrStrings.uni | 65 ++ DasharoModulePkg/DasharoModulePkg.dec | 1 + 10 files changed, 1819 insertions(+) create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.uni create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardExtra.uni create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr create mode 100644 DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni diff --git a/DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c b/DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c new file mode 100644 index 0000000000..d004536821 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c @@ -0,0 +1,468 @@ +/** @file +Sovereign Boot Wizard bootloader parsing. + +Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SovereignBootWizard.h" + +/// +/// Boot Option from variable Menu +/// +BM_MENU_OPTION BootOptionMenu = { + SOVEREIGN_BOOT_MENU_OPTION_SIGNATURE, + { NULL }, + 0 +}; + +/** + This function converts an input device structure to a Unicode string. + + @param DevPath A pointer to the device path structure. + + @return A new allocated Unicode string that represents the device path. + +**/ +CHAR16 * +UiDevicePathToStr ( + IN EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText, + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + CHAR16 *ToText; + + if (DevPath == NULL || DevPathToText == NULL) { + return NULL; + } + + ToText = DevPathToText->ConvertDevicePathToText ( + DevPath, + FALSE, + TRUE + ); + ASSERT (ToText != NULL); + return ToText; +} + +/** + Check if it's a Device Path pointing to FV file. + + The function doesn't guarantee the device path points to existing FV file. + + @param DevicePath Input device path. + + @retval TRUE The device path is a FV File Device Path. + @retval FALSE The device path is NOT a FV File Device Path. +**/ +BOOLEAN +IsFvFilePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *Path; + + Node = DevicePath; + Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &Handle); + if (!EFI_ERROR (Status)) { + return TRUE; + } + + Path = DevicePath; + + if ((DevicePathType (Path) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (Path) == HW_MEMMAP_DP)) { + Path = NextDevicePathNode (Path); + if ((DevicePathType (Path) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Path) == MEDIA_PIWG_FW_FILE_DP)) { + return IsDevicePathEnd (NextDevicePathNode (Path)); + } + } + + return FALSE; +} + +EFI_DEVICE_PATH_PROTOCOL * +StripFilePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Path; + EFI_DEVICE_PATH_PROTOCOL *Node; + + Path = DuplicateDevicePath(DevPath); + + if (Path == NULL) { + return NULL; + } + + for (Node = Path; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { + if ((DevicePathType (Node) == MEDIA_DEVICE_PATH) && + ((DevicePathSubType (Node) == MEDIA_FILEPATH_DP))) + { + SetDevicePathEndNode(Node); + return Path; + } + } + + // In case we did not found file path, free the duplicated path + FreePool (Path); + return NULL; +} + +EFI_DEVICE_PATH_PROTOCOL * +ExtractFilePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + + for (Node = DevPath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { + if ((DevicePathType (Node) == MEDIA_DEVICE_PATH) && + ((DevicePathSubType (Node) == MEDIA_FILEPATH_DP))) + { + return Node; + } + } + + return NULL; +} + +/** + Create a menu entry by given menu type. + + @param MenuType The Menu type to be created. + + @retval NULL If failed to create the menu. + @return the new menu entry. + +**/ +BM_MENU_ENTRY * +CreateMenuEntry ( + UINTN MenuType + ) +{ + BM_MENU_ENTRY *MenuEntry; + UINTN ContextSize; + + // + // Get context size according to menu type + // + switch (MenuType) { + case SOVEREIGN_BOOT_LOAD_CONTEXT_SELECT: + ContextSize = sizeof (BM_LOAD_CONTEXT); + break; + + case SOVEREIGN_BOOT_FILE_CONTEXT_SELECT: + ContextSize = sizeof (BM_FILE_CONTEXT); + break; + + default: + ContextSize = 0; + break; + } + + if (ContextSize == 0) { + return NULL; + } + + // + // Create new menu entry + // + MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY)); + if (MenuEntry == NULL) { + return NULL; + } + + MenuEntry->VariableContext = AllocateZeroPool (ContextSize); + if (MenuEntry->VariableContext == NULL) { + FreePool (MenuEntry); + return NULL; + } + + MenuEntry->Signature = SOVEREIGN_BOOT_MENU_ENTRY_SIGNATURE; + MenuEntry->ContextSelection = MenuType; + return MenuEntry; +} + +/** + + Build the BootOptionMenu according to BootOrder Variable. + This Routine will access the Boot#### to get EFI_LOAD_OPTION. + + @param CallbackData The BMM context data. + + @return EFI_NOT_FOUND Fail to find "BootOrder" variable. + @return EFI_SUCESS Success build boot option menu. + +**/ +EFI_STATUS +GetBootOptions ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private + ) +{ + UINTN Index; + CHAR16 BootString[10]; + UINT8 *LoadOptionFromVar; + UINTN BootOptionSize; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT8 *LoadOptionPtr; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINTN StringSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *HwDevicePath; + UINTN MenuCount; + UINT8 *Ptr; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + CHAR16 *PathString; + + MenuCount = 0; + BootOrderListSize = 0; + BootOrderList = NULL; + LoadOptionFromVar = NULL; + InitializeListHead (&BootOptionMenu.Head); + + // + // Get the BootOrder from the Var + // + GetEfiGlobalVariable2 (L"BootOrder", (VOID **)&BootOrderList, &BootOrderListSize); + if (BootOrderList == NULL) { + return EFI_NOT_FOUND; + } + + BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { + // + // Don't display the hidden/inactive boot option + // + if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || + ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) { + continue; + } + + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); + // + // Get all loadoptions from the VAR + // + GetEfiGlobalVariable2 (BootString, (VOID **)&LoadOptionFromVar, &BootOptionSize); + if (LoadOptionFromVar == NULL) { + continue; + } + + // + // Is a Legacy Device? + // + Ptr = (UINT8 *)LoadOptionFromVar; + + // + // Attribute = *(UINT32 *)Ptr; + // + Ptr += sizeof (UINT32); + + // + // FilePathSize = *(UINT16 *)Ptr; + // + Ptr += sizeof (UINT16); + + // + // Description = (CHAR16 *)Ptr; + // + Ptr += StrSize ((CHAR16 *)Ptr); + + // + // Now Ptr point to Device Path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr; + + // Skip boot options that point to FV + if (IsFvFilePath (DevicePath)) { + FreePool (LoadOptionFromVar); + continue; + } + + NewMenuEntry = CreateMenuEntry (SOVEREIGN_BOOT_LOAD_CONTEXT_SELECT); + ASSERT (NULL != NewMenuEntry); + + NewLoadContext = (BM_LOAD_CONTEXT *)NewMenuEntry->VariableContext; + + LoadOptionPtr = LoadOptionFromVar; + + NewMenuEntry->OptionNumber = BootOrderList[Index]; + + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + NewLoadContext->IsLegacy = TRUE; + } else { + NewLoadContext->IsLegacy = FALSE; + } + + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + + NewLoadContext->Attributes = *(UINT32 *)LoadOptionPtr; + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *)LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize (L"Description: ") + StrSize ((UINT16 *)LoadOptionPtr) + sizeof(CHAR16); + NewLoadContext->Description = AllocateZeroPool (StringSize); + ASSERT (NewLoadContext->Description != NULL); + UnicodeSPrint (NewLoadContext->Description, StringSize, L"Description: %s", LoadOptionPtr); + + NewMenuEntry->DisplayString = NewLoadContext->Description; + NewMenuEntry->DisplayStringToken = HiiSetString (Private->HiiHandle, 0, NewLoadContext->Description, NULL); + + LoadOptionPtr += StrSize ((UINT16 *)LoadOptionPtr); + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *)LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + // Hardware Path to the disk + HwDevicePath = StripFilePath (NewLoadContext->FilePathList); + if (HwDevicePath == NULL) { + // In case there is no file device path, it means it is /EFI/BOOT/BOOTX64.efi + // and is automatically expanded by UEFI boot manager + PathString = UiDevicePathToStr (Private->DevPathToText, NewLoadContext->FilePathList); + } else { + PathString = UiDevicePathToStr (Private->DevPathToText, HwDevicePath); + FreePool (HwDevicePath); + } + ASSERT (PathString != NULL); + StringSize = StrSize (L"Hardware path: ") + StrSize (PathString) + sizeof(CHAR16); + NewMenuEntry->DevicePathString = AllocateZeroPool (StringSize); + ASSERT (NewMenuEntry->DevicePathString != NULL); + UnicodeSPrint (NewMenuEntry->DevicePathString, StringSize, L"Hardware path: %s", PathString); + FreePool (PathString); + NewMenuEntry->DevicePathStringToken = HiiSetString (Private->HiiHandle, 0, NewMenuEntry->DevicePathString, NULL); + + // File path on the disk + if (HwDevicePath != NULL) { + PathString = UiDevicePathToStr (Private->DevPathToText, ExtractFilePath (NewLoadContext->FilePathList)); + ASSERT (PathString != NULL); + } else { + // In case there is no file device path, it means it is /EFI/BOOT/BOOTX64.efi + // and is automatically expanded by UEFI boot manager + PathString = EFI_REMOVABLE_MEDIA_FILE_NAME; + } + StringSize = StrSize (L"File path: ") + StrSize (PathString) + sizeof(CHAR16); + NewMenuEntry->FilePathString = AllocateZeroPool (StringSize); + ASSERT (NewMenuEntry->FilePathString != NULL); + UnicodeSPrint (NewMenuEntry->FilePathString, StringSize, L"File path: %s", PathString); + if (HwDevicePath != NULL) { + FreePool (PathString); + } + NewMenuEntry->FilePathStringToken = HiiSetString (Private->HiiHandle, 0, NewMenuEntry->FilePathString, NULL); + + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + MenuCount++; + FreePool (LoadOptionFromVar); + } + + EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); + + if (BootOrderList != NULL) { + FreePool (BootOrderList); + } + + DEBUG ((EFI_D_INFO, "Found %d boot options \n", MenuCount)); + + BootOptionMenu.MenuNumber = MenuCount; + return EFI_SUCCESS; +} + +/** + Get the Menu Entry from the list in Menu Entry List. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param MenuOption The Menu Entry List to read the menu entry. + @param MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +BM_MENU_ENTRY * +GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + if (MenuNumber >= MenuOption->MenuNumber) { + return NULL; + } + + List = MenuOption->Head.ForwardLink; + for (Index = 0; Index < MenuNumber; Index++) { + List = List->ForwardLink; + } + + NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, SOVEREIGN_BOOT_MENU_ENTRY_SIGNATURE); + + return NewMenuEntry; +} + +EFI_STATUS +UpdateBootloaderPage ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN UINTN OptionNumber + ) +{ + BM_MENU_ENTRY *BootloaderEntry; + BM_LOAD_CONTEXT *BootloaderContext; + EFI_STRING NewString; + + BootloaderEntry = GetMenuEntry (&BootOptionMenu, OptionNumber); + if (BootloaderEntry == NULL) { + return EFI_NO_MEDIA; + } + + BootloaderContext = (BM_LOAD_CONTEXT *)BootloaderEntry->VariableContext; + if (BootloaderContext == NULL) { + return EFI_NO_MEDIA; + } + + // Update strings on bootloader page + NewString = HiiGetString (Private->HiiHandle, BootloaderEntry->DisplayStringToken, NULL); + if (NewString != NULL) { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_BOOTOPT_DESCRIPTION), NewString, NULL); + } else { + return EFI_NOT_FOUND; + } + + NewString = HiiGetString (Private->HiiHandle, BootloaderEntry->DevicePathStringToken, NULL); + if (NewString != NULL) { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_HW_PATH), NewString, NULL); + } else { + return EFI_NOT_FOUND; + } + + NewString = HiiGetString (Private->HiiHandle, BootloaderEntry->FilePathStringToken, NULL); + if (NewString != NULL) { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_FILE_PATH), NewString, NULL); + } else { + return EFI_NOT_FOUND; + } + + // TODO fingerprint and key details + + return EFI_SUCCESS; +} diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c new file mode 100644 index 0000000000..e50f9f2192 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c @@ -0,0 +1,744 @@ +/** @file +Sovereign Boot Wizard implementation. + +Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SovereignBootWizard.h" + +SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *mPrivateData = NULL; +BOOLEAN mBootloadersInitted = FALSE; + +STATIC CHAR16 mSvBootDataVarName[] = L"SvBootData"; +STATIC CHAR16 mVarStoreName[] = L"SvBootFormData"; +STATIC CHAR16 mSvBootConfigVarName[] = L"SvBootConfig"; + +STATIC BOOLEAN mBootloadersShown = FALSE; + +STATIC HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + SOVEREIGN_BOOT_WIZARD_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +STATIC UINTN mBootloaderIndex = 0; + +EFI_STATUS +EFIAPI +SovereignBootWizardUnload ( + IN EFI_HANDLE ImageHandle + ); + + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +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_STATUS Status; + SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private; + UINTN BufferSize; + EFI_STRING ConfigRequestHdr; + EFI_STRING ConfigRequest; + UINTN Size; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + if (Request != NULL && + !HiiIsConfigHdrMatch (Request, &gSovereignBootWizardFormSetGuid, mVarStoreName)) { + return EFI_NOT_FOUND; + } + + Private = SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS (This); + + BufferSize = sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA); + ConfigRequest = Request; + if (Request == NULL || (StrStr (Request, L"OFFSET") == NULL)) { + // Request has no request element, construct full request string. + // Allocate and fill a buffer large enough to hold the template + // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator. + ConfigRequestHdr = HiiConstructConfigHdr ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + Private->AppHandle + ); + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); + ConfigRequest = AllocateZeroPool (Size); + ASSERT (ConfigRequest != NULL); + UnicodeSPrint ( + ConfigRequest, + Size, + L"%s&OFFSET=0&WIDTH=%016LX", + ConfigRequestHdr, + (UINT64) BufferSize + ); + FreePool (ConfigRequestHdr); + } + + // Convert fields of binary structure to string representation. + Status = Private->HiiConfigRouting->BlockToConfig ( + Private->HiiConfigRouting, + ConfigRequest, + (CONST UINT8 *) &Private->FormData, + BufferSize, + Results, + Progress + ); + ASSERT_EFI_ERROR (Status); + + // Free config request string if it was allocated. + if (ConfigRequest != Request) { + FreePool (ConfigRequest); + } + + if (Request != NULL && StrStr (Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen (Request); + } + + return Status; +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in + format. + @param Progress A pointer to a string filled in with the offset of + the most recent '&' before the first failing + name/value pair (or the beginning of the string if + the failure is in the first name/value pair) or + the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + @retval EFI_DEVICE_ERROR If value is 44, return error for testing. + +**/ +EFI_STATUS +EFIAPI +RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData; + + if ((Configuration == NULL) || (Progress == NULL)) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS (This); + *Progress = Configuration; + + if (!HiiIsConfigHdrMatch (Configuration, &gSovereignBootWizardFormSetGuid, NULL)) { + return EFI_NOT_FOUND; + } + + if (HiiIsConfigHdrMatch (Configuration, &gSovereignBootWizardFormSetGuid, mSvBootDataVarName)) { + return EFI_UNSUPPORTED; + } + + if (!HiiIsConfigHdrMatch (Configuration, &gSovereignBootWizardFormSetGuid, mSvBootConfigVarName)) { + return EFI_UNSUPPORTED; + } + + BufferSize = sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA); + Status = PrivateData->HiiConfigRouting->ConfigToBlock ( + PrivateData->HiiConfigRouting, + Configuration, + (UINT8 *)&PrivateData->FormData, + &BufferSize, + Progress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +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 EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData; + EFI_INPUT_KEY Key; + + if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) || + (ActionRequest == NULL)) + { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + PrivateData = SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS (This); + + DEBUG ((EFI_D_INFO, "Callback: Action %x QuestionID %x Type %x\n", Action, QuestionId, Type)); + + switch (Action) { + case EFI_BROWSER_ACTION_CHANGING: + switch (QuestionId) { + case SELECT_DEFAULT_SECURE_BOOT_QUESTION_ID: + { + // TODO: + // 1. Set the Sovering Boot option to disabled. + // 2. Unset the system provisioned state (just in case it was + // provisioned before). + // 3. Restore default keys if necessary. Maybe use NV VendorKeys to + // indicate if key restoration is required. + // 4. Reset the system to boot in a fresh state. Can't really avoid + // the reset as we cannot exit the form in any other action than + // EFI_BROWSER_ACTION_CHANGED, but it can't be invoked for + // EFI_IFR_TYPE_ACTION nor EFI_IFR_TYPE_REF. Also we should reset + // in case Secure Boto keys get restored to defaults. We can show + // a pop-up to inform about the actions we make here. + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + break; + } + default: + break; + } + + break; + case EFI_BROWSER_ACTION_CHANGED: + { + switch (QuestionId) { + case EXIT_FORM1_QUESTION_ID: + case EXIT_FORM2_QUESTION_ID: + case EXIT_FORM3_QUESTION_ID: + case EXIT_FORM9_QUESTION_ID: + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + break; + case DO_NOT_TRUST_KEY_FORM2_QUESTION_ID: + case TRUST_KEY_FORM2_QUESTION_ID: + if (mBootloadersInitted) { + Status = UpdateBootloaderPage (PrivateData, ++mBootloaderIndex); + if (Status == EFI_NO_MEDIA) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"No more bootloaders found.", + L"", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + // TODO: Here + // 1. If nothing has been selected as trusted so far, warn popup. + // 2. Create ephemeral PK. Enroll it and enable Secure Boot. + // 3. Set the SV boto variable to provisioned state. + // 4. Boot the first trusted bootloader. + + // No more bootloaders, reset the bootloader index and + // go to ineractive mode form for now. + mBootloaderIndex = 0; + Status = PrivateData->FormBrowser2->SendForm ( + PrivateData->FormBrowser2, + &PrivateData->HiiHandle, + 1, + &gSovereignBootWizardFormSetGuid, + SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID, + NULL, + ActionRequest + ); + } else if (Status == EFI_NOT_FOUND) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"Could not get bootloader description.", + L"", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + // Unexpected failure when parsing bootloader, reset bootloader index + // and go back to welcome form + mBootloaderIndex = 0; + Status = PrivateData->FormBrowser2->SendForm ( + PrivateData->FormBrowser2, + &PrivateData->HiiHandle, + 1, + &gSovereignBootWizardFormSetGuid, + SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID, + NULL, + ActionRequest + ); + } + } else { + Status = EFI_NO_MEDIA; + } + break; + default: + break; + } + + break; + } + case EFI_BROWSER_ACTION_FORM_OPEN: + { + switch (QuestionId) { + case DO_NOT_TRUST_KEY_FORM2_QUESTION_ID: + case TRUST_KEY_AND_BOOT_FORM2_QUESTION_ID: + case TRUST_KEY_FORM2_QUESTION_ID: + case SHOW_KEY_DETAILS_FORM2_QUESTION_ID: + if (!mBootloadersInitted) { + Status = GetBootOptions (PrivateData); + DEBUG ((EFI_D_INFO, "GetBootOptions: %r\n", mBootloaderIndex, Status)); + if (!EFI_ERROR (Status)) { + mBootloadersInitted = TRUE; + if (!mBootloadersShown) { + Status = UpdateBootloaderPage (PrivateData, mBootloaderIndex); + DEBUG ((EFI_D_INFO, "UpdateBootloaderPage(%d): %r\n", mBootloaderIndex, Status)); + mBootloadersShown = !EFI_ERROR (Status); + } + } else { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"Could not find any bootloaders.", + L"", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + // No bootloaders, go back to welcome form + Status = PrivateData->FormBrowser2->SendForm ( + PrivateData->FormBrowser2, + &PrivateData->HiiHandle, + 1, + &gSovereignBootWizardFormSetGuid, + SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID, + NULL, + NULL + ); + } + } + break; + + default: + break; + } + + break; + } + default: + Status = EFI_UNSUPPORTED; + break; + } + + return Status; +} + +/** + Main entry for this driver. + + @param ImageHandle Image handle this driver. + @param SystemTable Pointer to SystemTable. + + @retval EFI_SUCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +SovereignBootWizardInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS FormBrowserStatus; + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_SCREEN_DESCRIPTOR Screen; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_STRING_PROTOCOL *HiiString; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler; + EFI_HII_POPUP_PROTOCOL *PopupHandler; + UINTN BufferSize; + SOVEREIGN_BOOT_WIZARD_CONFIG_DATA *ConfigData; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG *SvConfig; + EFI_BOOT_MODE BootMode; + EFI_INPUT_KEY HotKey; + EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + CHAR16 *NewString; + EFI_HANDLE AppHandle; + + NewString = NULL; + AppHandle = NULL; + + ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR)); + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow); + + Screen.TopRow = 3; + Screen.BottomRow = Screen.BottomRow - 3; + + // + // Initialize driver private data + // + mPrivateData = AllocateZeroPool (sizeof (SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA)); + if (mPrivateData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mPrivateData->Signature = SOVEREIGN_BOOT_PRIVATE_SIGNATURE; + + mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig; + mPrivateData->ConfigAccess.RouteConfig = RouteConfig; + mPrivateData->ConfigAccess.Callback = Callback; + + // + // Locate Hii Database protocol + // + Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mPrivateData->HiiDatabase = HiiDatabase; + + // + // Locate HiiString protocol + // + Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **)&HiiString); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mPrivateData->HiiString = HiiString; + + // + // Locate Formbrowser2 protocol + // + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **)&FormBrowser2); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mPrivateData->FormBrowser2 = FormBrowser2; + + // + // Locate ConfigRouting protocol + // + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&HiiConfigRouting); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mPrivateData->HiiConfigRouting = HiiConfigRouting; + + // + // Locate keyword handler protocol + // + Status = gBS->LocateProtocol (&gEfiConfigKeywordHandlerProtocolGuid, NULL, (VOID **)&HiiKeywordHandler); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mPrivateData->HiiKeywordHandler = HiiKeywordHandler; + + // + // Locate HiiPopup protocol + // + Status = gBS->LocateProtocol (&gEfiHiiPopupProtocolGuid, NULL, (VOID **)&PopupHandler); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mPrivateData->HiiPopup = PopupHandler; + + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevPathToText); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mPrivateData->DevPathToText = DevPathToText; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &AppHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mPrivateData->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + mPrivateData->AppHandle = AppHandle; + + // + // Publish our HII data + // + HiiHandle = HiiAddPackages ( + &gSovereignBootWizardFormSetGuid, + AppHandle, + SovereignBootWizardVfrBin, + SovereignBootWizardStrings, + NULL + ); + if (HiiHandle == NULL) { + SovereignBootWizardUnload (ImageHandle); + return EFI_OUT_OF_RESOURCES; + } + + mPrivateData->HiiHandle = HiiHandle; + + SvConfig = &mPrivateData->NvConfig; + ZeroMem (SvConfig, sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG)); + + BufferSize = sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + Status = gRT->GetVariable (mSvBootConfigVarName, &gSovereignBootWizardFormSetGuid, NULL, &BufferSize, SvConfig); + if (EFI_ERROR (Status)) { + // If variable doesn't exist, store zero to indicate unprovisioned state. + Status = gRT->SetVariable ( + mSvBootConfigVarName, + &gSovereignBootWizardFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG), + SvConfig + ); + if (EFI_ERROR (Status)) { + SovereignBootWizardUnload (ImageHandle); + return Status; + } + } + + // Check Boot Mode + BootMode = GetBootModeHob (); + // On flash update do not run the application + if (BootMode == BOOT_ON_FLASH_UPDATE) { + SovereignBootWizardUnload (ImageHandle); + return EFI_UNSUPPORTED; + } + + // + // Initialize configuration data + // + ConfigData = &mPrivateData->ConfigData; + ZeroMem (ConfigData, sizeof (SOVEREIGN_BOOT_WIZARD_CONFIG_DATA)); + + BufferSize = sizeof (SOVEREIGN_BOOT_WIZARD_CONFIG_DATA); + Status = gRT->GetVariable (mSvBootDataVarName, &gSovereignBootWizardFormSetGuid, NULL, &BufferSize, ConfigData); + if (EFI_ERROR (Status)) { + // Unknown launch cause, try to determine if it is first launch or not + if (!SvConfig->SvBootProvisioned || + BootMode == BOOT_WITH_DEFAULT_SETTINGS || + BootMode == BOOT_WITH_MFG_MODE_SETTINGS + ) + { + ConfigData->AppLaunchCause = SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS; + } + } else { + // If not provisioned, the launch cause can only be undefined or boot with defaults + if (!SvConfig->SvBootProvisioned && + ConfigData->AppLaunchCause >= SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) + { + ConfigData->AppLaunchCause = SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS; + } + } + + // Handle invalid value + if (ConfigData->AppLaunchCause >= SV_BOOT_LAUNCH_MAX) { + ConfigData->AppLaunchCause = SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS; + } + + // + // Override Hotkeys, F9 and F10 won't be needed by this application + // + FormBrowserStatus = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **)&FormBrowserEx2); + if (!EFI_ERROR (FormBrowserStatus)) { + HotKey.UnicodeChar = CHAR_NULL; + HotKey.ScanCode = SCAN_F9; + FormBrowserEx2->RegisterHotKey (&HotKey, 0, 0, NULL); + HotKey.ScanCode = SCAN_F10; + FormBrowserEx2->RegisterHotKey (&HotKey, 0, 0, NULL); + } + + // + // turn off the watchdog timer + // + gBS->SetWatchdogTimer (0, 0, 0, NULL); + + // Display the form + Status = FormBrowser2->SendForm ( + FormBrowser2, + &HiiHandle, + 1, + &gSovereignBootWizardFormSetGuid, + SvConfig->SvBootProvisioned ? + SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID : + SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID, + NULL, + NULL + ); + + ASSERT_EFI_ERROR (Status); + + if (!EFI_ERROR (FormBrowserStatus)) { + // + // Register the default HotKey F9 and F10 again. + // + HotKey.UnicodeChar = CHAR_NULL; + HotKey.ScanCode = SCAN_F10; + NewString = HiiGetString (HiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL); + ASSERT (NewString != NULL); + FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString); + FreePool (NewString); + + HotKey.ScanCode = SCAN_F9; + NewString = HiiGetString (HiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL); + ASSERT (NewString != NULL); + FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString); + FreePool (NewString); + } + + Status = SovereignBootWizardUnload (ImageHandle); + + return Status; +} + +/** + Unloads the application and its installed protocol. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. +**/ +EFI_STATUS +EFIAPI +SovereignBootWizardUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + UINTN Index; + + ASSERT (mPrivateData != NULL); + + if (mPrivateData->HiiHandle != NULL) { + HiiRemovePackages (mPrivateData->HiiHandle); + } + + if (mPrivateData->AppHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + mPrivateData->AppHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mPrivateData->ConfigAccess, + NULL + ); + mPrivateData->AppHandle = NULL; + } + + for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) { + if (mPrivateData->NameValueName[Index] != NULL) { + FreePool (mPrivateData->NameValueName[Index]); + } + } + + FreePool (mPrivateData); + mPrivateData = NULL; + + return EFI_SUCCESS; +} diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h new file mode 100644 index 0000000000..9bd5f79ee1 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h @@ -0,0 +1,180 @@ +/** @file + +Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +Module Name: + + SovereignBootWizard.h + +Abstract: + + +Revision History + + +**/ + +#ifndef _DRIVER_SAMPLE_H_ +#define _DRIVER_SAMPLE_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "SovereignBootWizardHii.h" + +extern UINT8 SovereignBootWizardVfrBin[]; +extern UINT8 SovereignBootWizardStrings[]; + +#define NAME_VALUE_NAME_NUMBER 3 + +#define DEFAULT_CLASS_MANUFACTURING_VALUE 0xFF +#define DEFAULT_CLASS_STANDARD_VALUE 0x0 + +#define SOVEREIGN_BOOT_PRIVATE_SIGNATURE SIGNATURE_32 ('S', 'B', 'p', 's') +#define SOVEREIGN_BOOT_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u') +#define SOVEREIGN_BOOT_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('l', 'o', 'a', 'd') +#define SOVEREIGN_BOOT_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r') + +#define SOVEREIGN_BOOT_LOAD_CONTEXT_SELECT 0x0 +#define SOVEREIGN_BOOT_FILE_CONTEXT_SELECT 0x2 + +typedef struct { + UINTN Signature; + + EFI_HANDLE AppHandle; + EFI_HII_HANDLE HiiHandle; + SOVEREIGN_BOOT_WIZARD_CONFIG_DATA ConfigData; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG NvConfig; + SOVEREIGN_BOOT_WIZARD_FORM_DATA FormData; + + EFI_STRING_ID NameStringId[NAME_VALUE_NAME_NUMBER]; + EFI_STRING NameValueName[NAME_VALUE_NAME_NUMBER]; + + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_STRING_PROTOCOL *HiiString; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler; + EFI_HII_POPUP_PROTOCOL *HiiPopup; + + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; +} SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA; + +#define SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS(a) CR (a, SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA, ConfigAccess, SOVEREIGN_BOOT_PRIVATE_SIGNATURE) + +#pragma pack(1) + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +#pragma pack() + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} BM_MENU_OPTION; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *DevicePathString; + UINT16 *FilePathString; + EFI_STRING_ID DisplayStringToken; + EFI_STRING_ID DevicePathStringToken; + EFI_STRING_ID FilePathStringToken; + UINTN ContextSelection; + VOID *VariableContext; +} BM_MENU_ENTRY; + +typedef struct { + BOOLEAN IsBootNext; + BOOLEAN Deleted; + + BOOLEAN IsLegacy; + BOOLEAN IsFvOption; + + UINT32 Attributes; + UINT16 FilePathListLength; + UINT16 *Description; + EFI_DEVICE_PATH_PROTOCOL *FilePathList; +} BM_LOAD_CONTEXT; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FILE_HANDLE FHandle; + UINT16 *FileName; + EFI_FILE_SYSTEM_VOLUME_LABEL *Info; + + BOOLEAN IsRoot; + BOOLEAN IsDir; + BOOLEAN IsRemovableMedia; + BOOLEAN IsLoadFile; + BOOLEAN IsBootLegacy; +} BM_FILE_CONTEXT; + +extern BM_MENU_OPTION BootOptionMenu; + +EFI_STATUS +GetBootOptions ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private + ); + +BM_MENU_ENTRY * +GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ); + +EFI_STATUS +UpdateBootloaderPage ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN UINTN OptionNumber + ); + +#endif diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf new file mode 100644 index 0000000000..9580849b00 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf @@ -0,0 +1,81 @@ +## @file +# This is a Sovereign Boot Wizard application. +# +# This application help configuring UEFI Secure Boot. +# +# Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SovereignBootWizard + MODULE_UNI_FILE = SovereignBootWizard.uni + FILE_GUID = B57031B9-1ABB-45F8-A9CB-AC5AAD72AD31 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = SovereignBootWizardInit + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BootOptionParsing.c + SovereignBootWizard.c + SovereignBootWizardHii.h + SovereignBootWizardVfrStrings.uni + SovereignBootWizard.h + SovereignBootWizardVfr.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + BaseCryptLib + MemoryAllocationLib + UefiBootManagerLib + UefiBootServicesTableLib + UefiApplicationEntryPoint + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + HobLib + HiiLib + PrintLib + UefiLib + DevicePathLib + PeCoffLib + SecureBootVariableLib + SecureBootVariableProvisionLib + +[Guids] + gSovereignBootWizardFormSetGuid + +[Protocols] + ## PRODUCES # SovereignBootWizardFormSet + ## PRODUCES # SovereignBootWizardInventory + gEfiDevicePathProtocolGuid + gEfiHiiStringProtocolGuid ## CONSUMES + gEfiHiiConfigRoutingProtocolGuid ## CONSUMES + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEfiFormBrowser2ProtocolGuid ## CONSUMES + gEfiHiiDatabaseProtocolGuid ## CONSUMES + gEfiSimpleTextInputExProtocolGuid ## SOMETIMES_CONSUMES + gEdkiiFormBrowserEx2ProtocolGuid ## CONSUMES + gEfiConfigKeywordHandlerProtocolGuid ## CONSUMES + gEfiHiiPopupProtocolGuid ## CONSUMES + gEfiDevicePathToTextProtocolGuid ## CONSUMES + gEfiFirmwareVolume2ProtocolGuid ## CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + SovereignBootWizardExtra.uni diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.uni b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.uni new file mode 100644 index 0000000000..0ba3611e84 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.uni @@ -0,0 +1,15 @@ +// /** @file +// Sovereign Boot Provisioning Wizard. +// +// This application helps in configuring UEFI Secure Boot. +// +// Copyright (c) 2025, 3mdeb Sp. z o.o. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Sovereign Boot Provisioning Wizard" + +#string STR_MODULE_DESCRIPTION #language en-US "This application helps in configuring UEFI Secure Boot." diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardExtra.uni b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardExtra.uni new file mode 100644 index 0000000000..9a554bd9c8 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardExtra.uni @@ -0,0 +1,12 @@ +// /** @file +// SovereignBootWizard Localized Strings and Content +// +// Copyright (c) 2025, 3mdeb Sp. z o.o. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Sovereign Boot Wizard" diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h new file mode 100644 index 0000000000..1d00d147ee --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h @@ -0,0 +1,92 @@ +/** @file + +Copyright (c) 2025, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +Module Name: + + SovereignBootWizardHii.h + +Abstract: + + HII Data used by the Sovereign Boot Wizard application + +Revision History: + + +**/ + +#ifndef SOVEREIGN_BOOT_WIZARD_HII_H_ +#define SOVEREIGN_BOOT_WIZARD_HII_H_ + +#include +#include +#include + +#define SOVEREIGN_BOOT_WIZARD_FORM_DATA_VARSTORE_ID 0x0001 + +#define SOVEREIGN_BOOT_WIZARD_FORMSET_GUID \ + { \ + 0xB57031B9, 0x1ABB, 0x45F8, {0xA9, 0xCB, 0xAC, 0x5A, 0xAD, 0x72, 0xAD, 0x31} \ + } + +// Application launch causes. Determine the logic and screens showed +// when the application is launched. +// We want different screens and messages when: +// 1. SV Boot is proviosioned by image fails to verify. +// 2. SV Boot is not yet provisioned or platform booting with default settings. +// 3. Application is launched from setup +#define SV_BOOT_LAUNCH_UNDEFINED 0 +#define SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS 1 +#define SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED 2 +#define SV_BOOT_LAUNCH_VIA_SETUP 3 +#define SV_BOOT_LAUNCH_MAX 4 + +#define SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID 1 +#define SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID 2 +#define SOVEREIGN_BOOT_WIZARD_MS_SECURE_BOOT_FORM_ID 3 +#define SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID 9 + +// Question IDs +// Each form will reserve 0x100 IDs +#define SOVEREIGN_BOOT_WIZARD_FORM_QUESTION_ID_BASE 0x1000 +// Welcome form +#define WELCOME_FORM_QUESTION_ID_BASE 0x1100 +#define SELECT_SOVEREIGN_BOOT_QUESTION_ID 0x1101 +#define SELECT_DEFAULT_SECURE_BOOT_QUESTION_ID 0x1102 + +// Configuration form +#define CONFIG_FORM_QUESTION_ID_BASE 0x1200 +#define DO_NOT_TRUST_KEY_FORM2_QUESTION_ID 0x1201 +#define TRUST_KEY_AND_BOOT_FORM2_QUESTION_ID 0x1202 +#define TRUST_KEY_FORM2_QUESTION_ID 0x1203 +#define SHOW_KEY_DETAILS_FORM2_QUESTION_ID 0x1204 + +#define EXIT_FORM_QUESTION_ID_BASE 0x1F00 +#define EXIT_FORM1_QUESTION_ID 0x1F01 +#define EXIT_FORM2_QUESTION_ID 0x1F02 +#define EXIT_FORM3_QUESTION_ID 0x1F03 +#define EXIT_FORM9_QUESTION_ID 0x1F09 + +extern EFI_GUID gSovereignBootWizardFormSetGuid; + +#pragma pack(1) + +// Data passed from firmware via EFI variables (volatile, BS access) +typedef struct { + UINT8 AppLaunchCause; +} SOVEREIGN_BOOT_WIZARD_CONFIG_DATA; + +// State of SV Boot in EFI variables (non-volatile, BS access) +typedef struct { + BOOLEAN SvBootProvisioned; +} SOVEREIGN_BOOT_WIZARD_NV_CONFIG; + +// Form Data +typedef struct { + UINT8 Unused; +} SOVEREIGN_BOOT_WIZARD_FORM_DATA; + +#pragma pack() + +#endif diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr new file mode 100644 index 0000000000..85abfc5933 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr @@ -0,0 +1,161 @@ +///** @file +// +// Sovereign Boot Wizard Setup formset. +// +// Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//**/ + + +#include +#include "SovereignBootWizardHii.h" + + +formset + guid = SOVEREIGN_BOOT_WIZARD_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + // + // Define a Buffer Storage (EFI_IFR_VARSTORE) + // + varstore SOVEREIGN_BOOT_WIZARD_FORM_DATA, + varid = SOVEREIGN_BOOT_WIZARD_FORM_DATA_VARSTORE_ID, + name = SvBootFormData, + guid = SOVEREIGN_BOOT_WIZARD_FORMSET_GUID; + + efivarstore SOVEREIGN_BOOT_WIZARD_CONFIG_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS, + name = SvBootData, + guid = SOVEREIGN_BOOT_WIZARD_FORMSET_GUID; + + efivarstore SOVEREIGN_BOOT_WIZARD_NV_CONFIG, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = SvBootConfig, + guid = SOVEREIGN_BOOT_WIZARD_FORMSET_GUID; + + // + // Welcome window + // + form formid = SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID, + title = STRING_TOKEN(STR_FORM1_TITLE); + + subtitle text = STRING_TOKEN(STR_WELCOME_SUBTITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, + prompt = STRING_TOKEN(STR_SELECT_SOVEREIGN_BOOT), + help = STRING_TOKEN(STR_SELECT_SOVEREIGN_BOOT_HELP), + flags = INTERACTIVE, + key = SELECT_SOVEREIGN_BOOT_QUESTION_ID; + + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_SOVEREIGN_BOOT_FEATURES); + endif; + + goto SOVEREIGN_BOOT_WIZARD_MS_SECURE_BOOT_FORM_ID, + prompt = STRING_TOKEN(STR_SELECT_DEFAULT_SECURE_BOOT), + help = STRING_TOKEN(STR_SELECT_DEFAULT_SECURE_BOOT_HELP), + flags = INTERACTIVE, + key = SELECT_DEFAULT_SECURE_BOOT_QUESTION_ID; + + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_MS_SECURE_BOOT_FEATURES); + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EXIT_TEXT), + flags = INTERACTIVE, + key = EXIT_FORM1_QUESTION_ID; + + endform; + + // + // SV boot configuration window + // + form formid = SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, + title = STRING_TOKEN(STR_FORM2_TITLE); + + subtitle text = STRING_TOKEN(STR_CONFIG_SUBTITLE); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + subtitle text = STRING_TOKEN(STR_BOOTOPT_DESCRIPTION); + subtitle text = STRING_TOKEN(STR_HW_PATH); + subtitle text = STRING_TOKEN(STR_FILE_PATH); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + subtitle text = STRING_TOKEN(STR_KEY_FINGERPRINT); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + subtitle text = STRING_TOKEN(STR_TRUST_QUESTION); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_DO_NOT_TRUST_KEY), + flags = INTERACTIVE, + key = DO_NOT_TRUST_KEY_FORM2_QUESTION_ID; + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_TRUST_KEY_AND_BOOT), + flags = INTERACTIVE, + key = TRUST_KEY_AND_BOOT_FORM2_QUESTION_ID; + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_TRUST_KEY), + flags = INTERACTIVE, + key = TRUST_KEY_FORM2_QUESTION_ID; + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_SHOW_KEY_DETAILS), + flags = INTERACTIVE, + key = SHOW_KEY_DETAILS_FORM2_QUESTION_ID; + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EXIT_TEXT), + flags = INTERACTIVE, + key = EXIT_FORM2_QUESTION_ID; + + endform; + + // + // Empty placeholder menu when MS Secure boot is chosen. + // The callback will simply exit the application when entering this form. + // + form formid = SOVEREIGN_BOOT_WIZARD_MS_SECURE_BOOT_FORM_ID, + title = STRING_TOKEN(STR_FORM1_TITLE); + endform; + + // + // Advanced mode window + // + form formid = SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID, + title = STRING_TOKEN(STR_FORM9_TITLE); + + subtitle text = STRING_TOKEN(STR_INTERACTIVE_MODE_SUBTITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EXIT_TEXT), + flags = INTERACTIVE, + key = EXIT_FORM9_QUESTION_ID; + + endform; + +endformset; diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni new file mode 100644 index 0000000000..ff3a7c3e08 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni @@ -0,0 +1,65 @@ +// *++ +// +// Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// Module Name: +// +// SovereignBootWizardVfrStrings.uni +// +// Abstract: +// +// String definitions for Sovereign Boot Wizard formset. +// +// Revision History: +// +// --*/ + + +/=# + +#langdef en-US "English" + +#string STR_FORM_SET_TITLE #language en-US "Sovereign Boot Provisioning Wizard" +#string STR_FORM_SET_TITLE_HELP #language en-US "" +#string STR_EMPTY_STRING #language en-US "" +#string STR_EXIT_TEXT #language en-US "[Exit]" + +#string FUNCTION_NINE_STRING #language en-US "F9=Reset to Defaults" +#string FUNCTION_TEN_STRING #language en-US "F10=Save" + +// Welcome page strings +#string STR_FORM1_TITLE #language en-US "Sovereign Boot Provisioning Wizard" +#string STR_WELCOME_SUBTITLE #language en-US "Welcome to Sovereign Boot Provisioning Wizard!" + +#string STR_SELECT_SOVEREIGN_BOOT #language en-US "Sovereign Boot" +#string STR_SELECT_SOVEREIGN_BOOT_HELP #language en-US "" +#string STR_SOVEREIGN_BOOT_FEATURES #language en-US "* You decide which keys to trust\n" + "* No keys are initially trusted by default\n" + "* Requires a Sovereign Boot compatible operating system" +#string STR_SELECT_DEFAULT_SECURE_BOOT #language en-US "Standard Secure Boot with Microsoft certificates" +#string STR_SELECT_DEFAULT_SECURE_BOOT_HELP #language en-US "" +#string STR_MS_SECURE_BOOT_FEATURES #language en-US "* Trust firmware's default certificates\n" + "* Compatible with common operating systems\n" + "* Does not modify current Secure Boot settings" + +// Configuration page strings +#string STR_FORM2_TITLE #language en-US "Sovereign Boot Provisioning Wizard" + +#string STR_CONFIG_SUBTITLE #language en-US "A new bootloader key has been detected." + +#string STR_BOOTOPT_DESCRIPTION #language en-US "Description: " +#string STR_HW_PATH #language en-US "Hardware path: " +#string STR_FILE_PATH #language en-US "File path: " +#string STR_KEY_FINGERPRINT #language en-US "Key fingerprint (SHA-256): " + +#string STR_TRUST_QUESTION #language en-US "Do you want to trust this key/image and continue booting?" + +#string STR_DO_NOT_TRUST_KEY #language en-US "[Do NOT trust, next key/bootloader]" +#string STR_TRUST_KEY_AND_BOOT #language en-US "[Trust this key and boot]" +#string STR_TRUST_KEY #language en-US "[Trust this key, next key/bootloader]" +#string STR_SHOW_KEY_DETAILS #language en-US "[Show key/certificate details]" + +// Interactive mode strings +#string STR_FORM9_TITLE #language en-US "Sovereign Boot Provisioning Wizard" +#string STR_INTERACTIVE_MODE_SUBTITLE #language en-US "Sovereign Boot is already provisioned. You can use below options to modify/augment current configuration\n" diff --git a/DasharoModulePkg/DasharoModulePkg.dec b/DasharoModulePkg/DasharoModulePkg.dec index 9271aaef3d..c2590fffd7 100644 --- a/DasharoModulePkg/DasharoModulePkg.dec +++ b/DasharoModulePkg/DasharoModulePkg.dec @@ -28,6 +28,7 @@ gUserAuthFeaturePkgTokenSpaceGuid = {0xa2793a6e, 0x6af1, 0x45c4, {0x88, 0x4d, 0x3d, 0x0c, 0x7a, 0xfe, 0x91, 0xc6}} ## Include Include/Guid/UserAuthentication.h gUserAuthenticationGuid = { 0xee24a7f7, 0x606b, 0x4724, { 0xb3, 0xc9, 0xf5, 0xae, 0x4a, 0x3b, 0x81, 0x65}} + gSovereignBootWizardFormSetGuid = { 0xb57031b9, 0x1abb, 0x45f8, {0xa9, 0xcb, 0xac, 0x5a, 0xad, 0x72, 0xad, 0x31}} [Ppis] From b9526c4300f252a53e9df77bf39c7c7a40aad209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Tue, 24 Jun 2025 15:29:42 +0200 Subject: [PATCH 02/15] OvmfPkg/OvmfPkgX64.dsc: Build Sovereign Boot Wizard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- OvmfPkg/OvmfPkgX64.dsc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index ebc3f821e4..f9518cdd0a 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -1053,6 +1053,8 @@ !endif !endif + DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf + # # Hash2 # From 1e2bd11cf80ca677d2fb14f0aeed504e776320ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Wed, 25 Jun 2025 13:05:41 +0200 Subject: [PATCH 03/15] DasharoModulePkg/SovereignBootWizard: Do not select any mode on welcome form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../SovereignBootWizard/SovereignBootWizardVfr.vfr | 8 +++++++- .../SovereignBootWizard/SovereignBootWizardVfrStrings.uni | 7 ++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr index 85abfc5933..487b676f52 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr @@ -44,7 +44,11 @@ formset subtitle text = STRING_TOKEN(STR_WELCOME_SUBTITLE); - subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + // Empty text field so that none of the options are + // highlighted/selected by default. + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EMPTY_STRING); goto SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, prompt = STRING_TOKEN(STR_SELECT_SOVEREIGN_BOOT), @@ -58,6 +62,8 @@ formset text = STRING_TOKEN(STR_SOVEREIGN_BOOT_FEATURES); endif; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + goto SOVEREIGN_BOOT_WIZARD_MS_SECURE_BOOT_FORM_ID, prompt = STRING_TOKEN(STR_SELECT_DEFAULT_SECURE_BOOT), help = STRING_TOKEN(STR_SELECT_DEFAULT_SECURE_BOOT_HELP), diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni index ff3a7c3e08..2e2b8f8e13 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni @@ -21,8 +21,8 @@ #langdef en-US "English" #string STR_FORM_SET_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_FORM_SET_TITLE_HELP #language en-US "" -#string STR_EMPTY_STRING #language en-US "" +#string STR_FORM_SET_TITLE_HELP #language en-US " " +#string STR_EMPTY_STRING #language en-US " " #string STR_EXIT_TEXT #language en-US "[Exit]" #string FUNCTION_NINE_STRING #language en-US "F9=Reset to Defaults" @@ -30,7 +30,8 @@ // Welcome page strings #string STR_FORM1_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_WELCOME_SUBTITLE #language en-US "Welcome to Sovereign Boot Provisioning Wizard!" +#string STR_WELCOME_SUBTITLE #language en-US "Welcome to Sovereign Boot Provisioning Wizard!\n\n" + "Please select the UEFI Secure Boot scheme you would like to use:" #string STR_SELECT_SOVEREIGN_BOOT #language en-US "Sovereign Boot" #string STR_SELECT_SOVEREIGN_BOOT_HELP #language en-US "" From 8c4ba1b7efdc01ee190d83b21068e3f87c8cb862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Wed, 25 Jun 2025 17:51:01 +0200 Subject: [PATCH 04/15] DasharoModulePkg: Autocreate Sovereign Boot variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../SovereignBootWizard/SovereignBootWizard.c | 4 +- .../SovereignBootWizard/SovereignBootWizard.h | 4 +- .../SovereignBootWizardHii.h | 29 +---------- DasharoModulePkg/DasharoModulePkg.dec | 2 + DasharoModulePkg/Include/DasharoOptions.h | 4 ++ DasharoModulePkg/Include/Guid/SovereignBoot.h | 48 +++++++++++++++++ .../DasharoVariablesLib/DasharoVariablesLib.c | 51 ++++++++++++++----- .../DasharoVariablesLib.inf | 3 ++ 8 files changed, 101 insertions(+), 44 deletions(-) create mode 100644 DasharoModulePkg/Include/Guid/SovereignBoot.h diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c index e50f9f2192..01e632d4b0 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c @@ -11,9 +11,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *mPrivateData = NULL; BOOLEAN mBootloadersInitted = FALSE; -STATIC CHAR16 mSvBootDataVarName[] = L"SvBootData"; +STATIC CHAR16 mSvBootDataVarName[] = SV_BOOT_DATA_VAR; STATIC CHAR16 mVarStoreName[] = L"SvBootFormData"; -STATIC CHAR16 mSvBootConfigVarName[] = L"SvBootConfig"; +STATIC CHAR16 mSvBootConfigVarName[] = SV_BOOT_CONFIG_VAR; STATIC BOOLEAN mBootloadersShown = FALSE; diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h index 9bd5f79ee1..4b69ea7046 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h @@ -15,8 +15,8 @@ Revision History **/ -#ifndef _DRIVER_SAMPLE_H_ -#define _DRIVER_SAMPLE_H_ +#ifndef _SV_BOOT_WIZARD_H_ +#define _SV_BOOT_WIZARD_H_ #include diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h index 1d00d147ee..f5b82fd765 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h @@ -21,27 +21,11 @@ Revision History: #include #include +#include #include #define SOVEREIGN_BOOT_WIZARD_FORM_DATA_VARSTORE_ID 0x0001 -#define SOVEREIGN_BOOT_WIZARD_FORMSET_GUID \ - { \ - 0xB57031B9, 0x1ABB, 0x45F8, {0xA9, 0xCB, 0xAC, 0x5A, 0xAD, 0x72, 0xAD, 0x31} \ - } - -// Application launch causes. Determine the logic and screens showed -// when the application is launched. -// We want different screens and messages when: -// 1. SV Boot is proviosioned by image fails to verify. -// 2. SV Boot is not yet provisioned or platform booting with default settings. -// 3. Application is launched from setup -#define SV_BOOT_LAUNCH_UNDEFINED 0 -#define SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS 1 -#define SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED 2 -#define SV_BOOT_LAUNCH_VIA_SETUP 3 -#define SV_BOOT_LAUNCH_MAX 4 - #define SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID 1 #define SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID 2 #define SOVEREIGN_BOOT_WIZARD_MS_SECURE_BOOT_FORM_ID 3 @@ -68,20 +52,9 @@ Revision History: #define EXIT_FORM3_QUESTION_ID 0x1F03 #define EXIT_FORM9_QUESTION_ID 0x1F09 -extern EFI_GUID gSovereignBootWizardFormSetGuid; #pragma pack(1) -// Data passed from firmware via EFI variables (volatile, BS access) -typedef struct { - UINT8 AppLaunchCause; -} SOVEREIGN_BOOT_WIZARD_CONFIG_DATA; - -// State of SV Boot in EFI variables (non-volatile, BS access) -typedef struct { - BOOLEAN SvBootProvisioned; -} SOVEREIGN_BOOT_WIZARD_NV_CONFIG; - // Form Data typedef struct { UINT8 Unused; diff --git a/DasharoModulePkg/DasharoModulePkg.dec b/DasharoModulePkg/DasharoModulePkg.dec index c2590fffd7..512ce80fd8 100644 --- a/DasharoModulePkg/DasharoModulePkg.dec +++ b/DasharoModulePkg/DasharoModulePkg.dec @@ -90,6 +90,8 @@ gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemorySpdProfileOption|FALSE|BOOLEAN|0x00000002F gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemoryIbeccOption|FALSE|BOOLEAN|0x000000030 gDasharoSystemFeaturesTokenSpaceGuid.PcdFumAutoIpxeBoot|TRUE|BOOLEAN|0x000000031 + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled|FALSE|BOOLEAN|0x000000032 + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState|FALSE|BOOLEAN|0x000000033 [PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx] ## Indicate whether the password is cleared. diff --git a/DasharoModulePkg/Include/DasharoOptions.h b/DasharoModulePkg/Include/DasharoOptions.h index 26ad167c6e..0c310531a5 100644 --- a/DasharoModulePkg/Include/DasharoOptions.h +++ b/DasharoModulePkg/Include/DasharoOptions.h @@ -9,6 +9,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #ifndef _DASHARO_OPTIONS_H_ #define _DASHARO_OPTIONS_H_ +#include + // // Names of Dasharo-specific EFI variables in DasharoSystemFeaturesGuid // namespace. @@ -125,6 +127,8 @@ typedef union { DASHARO_WATCHDOG_CONFIG Watchdog; DASHARO_IOMMU_CONFIG Iommu; DASHARO_BATTERY_CONFIG Battery; + + SOVEREIGN_BOOT_WIZARD_NV_CONFIG SvBoot; } DASHARO_VAR_DATA; #endif diff --git a/DasharoModulePkg/Include/Guid/SovereignBoot.h b/DasharoModulePkg/Include/Guid/SovereignBoot.h new file mode 100644 index 0000000000..e3c2d5b4e3 --- /dev/null +++ b/DasharoModulePkg/Include/Guid/SovereignBoot.h @@ -0,0 +1,48 @@ +/** @file + +Copyright (c) 2025, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SOVEREIGN_BOOT_H_ +#define SOVEREIGN_BOOT_H_ + +#define SOVEREIGN_BOOT_WIZARD_FORMSET_GUID \ + { \ + 0xB57031B9, 0x1ABB, 0x45F8, {0xA9, 0xCB, 0xAC, 0x5A, 0xAD, 0x72, 0xAD, 0x31} \ + } + +#define SV_BOOT_DATA_VAR L"SvBootData" +#define SV_BOOT_CONFIG_VAR L"SvBootConfig" + +// Application launch causes. Determine the logic and screens showed +// when the application is launched. +// We want different screens and messages when: +// 1. SV Boot is proviosioned by image fails to verify. +// 2. SV Boot is not yet provisioned or platform booting with default settings. +// 3. Application is launched from setup +#define SV_BOOT_LAUNCH_UNDEFINED 0 +#define SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS 1 +#define SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED 2 +#define SV_BOOT_LAUNCH_VIA_SETUP 3 +#define SV_BOOT_LAUNCH_MAX 4 + +extern EFI_GUID gSovereignBootWizardFormSetGuid; + +#pragma pack(1) + +// Data passed from firmware via EFI variables (volatile, BS access) +typedef struct { + UINT8 AppLaunchCause; +} SOVEREIGN_BOOT_WIZARD_CONFIG_DATA; + +// State of SV Boot in EFI variables (non-volatile, BS access) +typedef struct { + BOOLEAN SvBootEnabled; + BOOLEAN SvBootProvisioned; +} SOVEREIGN_BOOT_WIZARD_NV_CONFIG; + +#pragma pack() + +#endif diff --git a/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c index ed86edf36c..ee1f62c6bd 100644 --- a/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c +++ b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c @@ -32,7 +32,8 @@ typedef struct { DASHARO_VAR_DATA Data; // Value for the variable. UINTN Size; // Number of bytes of Data actually used. - UINT32 Attributes; // EFI variable attributes for this variable. + UINT32 Attributes; // EFI variable attributes for this variable. + EFI_GUID *Guid; // GUID for this variable } VAR_INFO; typedef struct { @@ -76,6 +77,7 @@ STATIC CONST AUTO_VARIABLE mAutoCreatedVariables[] = { { DASHARO_VAR_FAST_BOOT, FixedPcdGetBool (PcdFastBootFeatureEnabled) }, { DASHARO_VAR_USB_PORT_POWER, FixedPcdGetBool (PcdShowPowerMenu) && FixedPcdGetBool (PcdPowerMenuShowUsbPowerOption) }, { DASHARO_VAR_DGPU_STATE, FixedPcdGetBool (PcdShowPowerMenu) && FixedPcdGetBool (PcdPowerMenuShowDGPUPowerOption) }, + { SV_BOOT_CONFIG_VAR, FixedPcdGetBool (PcdSovereignBootEnabled) }, }; /** @@ -95,10 +97,12 @@ GetVariableInfo ( DASHARO_VAR_DATA Data; UINTN Size; UINT32 ExtraAttrs; + EFI_GUID *VarGuid; SetMem (&Data, sizeof (Data), 0); Size = 0; ExtraAttrs = 0; + VarGuid = &gDasharoSystemFeaturesGuid; if (StrCmp (VarName, DASHARO_VAR_BATTERY_CONFIG) == 0) { Data.Battery.StartThreshold = 95; @@ -203,6 +207,11 @@ GetVariableInfo ( } else if (StrCmp (VarName, DASHARO_VAR_DGPU_STATE) == 0) { Data.Uint8 = DASHARO_DGPU_ENABLED; Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, SV_BOOT_CONFIG_VAR) == 0) { + Data.SvBoot.SvBootEnabled = FixedPcdGetBool (PcdSovereignBootDefaultState); + Data.SvBoot.SvBootProvisioned = FALSE; + Size = sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + VarGuid = &gSovereignBootWizardFormSetGuid; } else { DEBUG ((EFI_D_ERROR, "%a(): Unknown variable: %s.\n", __FUNCTION__, VarName)); ASSERT ((0 && "No default value set for a variable.")); @@ -211,6 +220,7 @@ GetVariableInfo ( Value.Data = Data; Value.Size = Size; Value.Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE | ExtraAttrs; + Value.Guid = VarGuid; return Value; } @@ -269,7 +279,7 @@ ResetVariable ( Status = gRT->SetVariable ( VarName, - &gDasharoSystemFeaturesGuid, + VarInfo.Guid, VarInfo.Attributes, VarInfo.Size, &VarInfo.Data @@ -288,18 +298,21 @@ ResetVariable ( STATIC VOID InitVariable ( - CHAR16 *VarName + CHAR16 *VarName ) { EFI_STATUS Status; UINTN BufferSize; UINT32 Attributes; VOID *VariableData; + VAR_INFO VarInfo; + + VarInfo = GetVariableInfo (VarName); BufferSize = 0; Status = gRT->GetVariable ( VarName, - &gDasharoSystemFeaturesGuid, + VarInfo.Guid, &Attributes, &BufferSize, NULL @@ -308,7 +321,7 @@ InitVariable ( if (Status == EFI_NOT_FOUND) { Status = ResetVariable (VarName); ASSERT_EFI_ERROR (Status); - } else if (Status == EFI_BUFFER_TOO_SMALL && Attributes != DasharoGetVariableAttributes(VarName)) { + } else if (Status == EFI_BUFFER_TOO_SMALL && Attributes != VarInfo.Attributes) { // Re-create variable with proper attributes if they don't match, preserving // the value. VariableData = AllocateZeroPool (BufferSize); @@ -316,7 +329,7 @@ InitVariable ( Status = gRT->GetVariable ( VarName, - &gDasharoSystemFeaturesGuid, + VarInfo.Guid, 0, &BufferSize, VariableData @@ -325,7 +338,7 @@ InitVariable ( Status = gRT->SetVariable ( VarName, - &gDasharoSystemFeaturesGuid, + VarInfo.Guid, 0, 0, NULL @@ -334,8 +347,8 @@ InitVariable ( Status = gRT->SetVariable ( VarName, - &gDasharoSystemFeaturesGuid, - DasharoGetVariableAttributes(VarName), + VarInfo.Guid, + VarInfo.Attributes, BufferSize, VariableData ); @@ -546,13 +559,27 @@ DasharoMeasureVariables ( VOID ) { + EFI_STATUS RetStatus; EFI_STATUS Status; + RetStatus = EFI_SUCCESS; + Status = MeasureVariables (&gDasharoSystemFeaturesGuid); - if (Status == EFI_SUCCESS) - Status = MeasureVariables (&gApuConfigurationFormsetGuid); + if (EFI_ERROR (Status)) { + RetStatus = Status; + } - return Status; + Status |= MeasureVariables (&gApuConfigurationFormsetGuid); + if (EFI_ERROR (Status)) { + RetStatus = Status; + } + + Status |= MeasureVariables (&gSovereignBootWizardFormSetGuid); + if (EFI_ERROR (Status)) { + RetStatus = Status; + } + + return RetStatus; } /** diff --git a/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf index 5668a0d78d..01785a9b94 100644 --- a/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf +++ b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf @@ -41,6 +41,7 @@ [Guids] gDasharoSystemFeaturesGuid ### CONSUMES gApuConfigurationFormsetGuid ### SOMETIMES CONSUMES + gSovereignBootWizardFormSetGuid ### SOMETIMES CONSUMES [Pcd] gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu @@ -87,6 +88,8 @@ gDasharoSystemFeaturesTokenSpaceGuid.PcdDgpuOnlyAvailable gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemorySpdProfileOption gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemoryIbeccOption + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState gEfiMdePkgTokenSpaceGuid.PcdFastBootFeatureEnabled gEfiMdePkgTokenSpaceGuid.PcdQuietBootFeatureEnabled gDasharoPayloadPkgTokenSpaceGuid.PcdLoadOptionRoms From 7ad4bd1b31f44ae66f5be912543340cd554a0dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 26 Jun 2025 13:51:22 +0200 Subject: [PATCH 05/15] SecurityPkg/VariableAuthenticated/SecureBootConfigDxe: Add SV Boot options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../SecureBootConfigDxe/SecureBootConfig.vfr | 30 ++ .../SecureBootConfigDxe.inf | 7 + .../SecureBootConfigImpl.c | 275 ++++++++++++++++++ .../SecureBootConfigImpl.h | 4 + .../SecureBootConfigNvData.h | 6 + .../SecureBootConfigStrings.uni | 17 ++ 6 files changed, 339 insertions(+) diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr index 88622f503f..2ca5b88cfd 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr @@ -70,6 +70,36 @@ formset endif; endif; + disableif ideqval SECUREBOOT_CONFIGURATION.SvBootAvailable == 0; + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_SOVEREIGN_BOOT_OPTIONS); + subtitle text = STRING_TOKEN(STR_NULL); + + checkbox varid = SECUREBOOT_CONFIGURATION.SvBootEnable, + questionid = KEY_SOVEREIGN_BOOT_ENABLE, + prompt = STRING_TOKEN(STR_ENABLE_SOVEREIGN_BOOT_PROMPT), + help = STRING_TOKEN(STR_ENABLE_SOVEREIGN_BOOT_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + endcheckbox; + + disableif ideqval SECUREBOOT_CONFIGURATION.SvBootEnable == 0; + subtitle text = STRING_TOKEN(STR_NULL); + // + // We may hide the menu if Sovereign Boot is not yet provisioned and allow to + // launch the wizard only when system is provisioned to augment the settings. + // + // suppressif ideqval SECUREBOOT_CONFIGURATION.SvBootProvisioned == 0; + text + help = STRING_TOKEN(STR_LAUNCH_SOVEREIGN_BOOT_WIZARD_HELP), + text = STRING_TOKEN(STR_LAUNCH_SOVEREIGN_BOOT_WIZARD_PROMPT), + flags = INTERACTIVE, + key = KEY_LAUNCH_SOVEREIGN_BOOT_WIZARD; + // endif; + endif; + + endif; + endform; // diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf index d923bd2be6..28734b6b42 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf @@ -37,6 +37,7 @@ MdeModulePkg/MdeModulePkg.dec SecurityPkg/SecurityPkg.dec CryptoPkg/CryptoPkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] BaseLib @@ -44,6 +45,7 @@ BaseCryptLib MemoryAllocationLib UefiLib + UefiBootManagerLib UefiBootServicesTableLib UefiRuntimeServicesTableLib UefiDriverEntryPoint @@ -60,6 +62,8 @@ [FixedPcd] gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState [Guids] ## SOMETIMES_CONSUMES ## Variable:L"CustomMode" @@ -132,11 +136,14 @@ gEfiCertX509Sha512Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the certificate. gEfiCertX509Sm3Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the certificate. + gSovereignBootWizardFormSetGuid ## SOMETIMES CONSUMES + [Protocols] gEfiHiiConfigAccessProtocolGuid ## PRODUCES gEfiDevicePathProtocolGuid ## PRODUCES gEfiHiiPopupProtocolGuid gEfiRealTimeClockArchProtocolGuid ## CONSUMES + gEdkiiFormBrowserEx2ProtocolGuid ## SOMETIMES_CONSUMES [Depex] gEfiHiiConfigRoutingProtocolGuid AND diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index 629f95cd18..f2bc7a1574 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -298,6 +298,58 @@ SaveSecureBootVariable ( return Status; } +/** + Set Sovereign Boot configuration into variable space. + + @param[in] SvBootEnable The satte of Sovereign Boot. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +SaveSovereignBootVariable ( + IN BOOLEAN SvBootEnable + ) +{ + SOVEREIGN_BOOT_WIZARD_NV_CONFIG SvBootConfig; + EFI_STATUS Status; + UINT32 Attrs; + UINTN VarSize; + + VarSize = sizeof(SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + + Status = gRT->GetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + &Attrs, + &VarSize, + &SvBootConfig + ); + + if (EFI_ERROR (Status) || + Attrs != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS) || + VarSize != sizeof(SOVEREIGN_BOOT_WIZARD_NV_CONFIG) + ) { + SvBootConfig.SvBootProvisioned = FALSE; + } + + if (SvBootConfig.SvBootEnabled == SvBootEnable) { + return EFI_SUCCESS; + } + + SvBootConfig.SvBootEnabled = SvBootEnable; + + Status = gRT->SetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG), + &SvBootConfig + ); + return Status; +} + /** This code checks if the encode type and key strength of X.509 certificate is qualified. @@ -3461,9 +3513,12 @@ SecureBootExtractConfigFromVariable ( UINT8 *SecureBootMode; EFI_TIME CurrTime; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG *SvBootConfig; + SecureBootEnable = NULL; SetupMode = NULL; SecureBootMode = NULL; + SvBootConfig = NULL; // // Initialize the Date and Time using system time. @@ -3534,6 +3589,21 @@ SecureBootExtractConfigFromVariable ( ConfigData->SecureBootMode = *(SecureBootMode); } + ConfigData->SvBootAvailable = FixedPcdGetBool (PcdSovereignBootEnabled); + ConfigData->SvBootEnable = FixedPcdGetBool (PcdSovereignBootDefaultState); + ConfigData->SvBootProvisioned = FALSE; + + if (ConfigData->SvBootAvailable) { + + GetVariable2 (SV_BOOT_CONFIG_VAR, &gSovereignBootWizardFormSetGuid, (VOID **)&SvBootConfig, NULL); + + if (SvBootConfig != NULL) { + ConfigData->SvBootEnable = SvBootConfig->SvBootEnabled; + ConfigData->SvBootProvisioned = SvBootConfig->SvBootProvisioned; + FreePool (SvBootConfig); + } + } + if (SecureBootEnable != NULL) { FreePool (SecureBootEnable); } @@ -3734,6 +3804,13 @@ SecureBootRouteConfig ( } } + if (IfrNvData.SvBootAvailable) { + Status = SaveSovereignBootVariable (IfrNvData.SvBootEnable); + if (EFI_ERROR (Status)) { + return Status; + } + } + *Progress = Configuration + StrLen (Configuration); return EFI_SUCCESS; } @@ -4725,6 +4802,140 @@ KeyEraseAll ( return Status; } +/** + + Check whether a reset is needed, if reset is needed, Popup a menu to notice user. + +**/ +VOID +SetupResetReminder ( + VOID + ) +{ + EFI_INPUT_KEY Key; + CHAR16 *StringBuffer1; + CHAR16 *StringBuffer2; + EFI_STATUS Status; + EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2; + + // + // Use BrowserEx2 protocol to check whether reset is required. + // + Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **)&FormBrowserEx2); + + // + // check any reset required change is applied? if yes, reset system + // + if (!EFI_ERROR (Status) && FormBrowserEx2->IsResetRequired ()) { + StringBuffer1 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16)); + ASSERT (StringBuffer1 != NULL); + StringBuffer2 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16)); + ASSERT (StringBuffer2 != NULL); + StrCpyS (StringBuffer1, MAX_CHAR, L"Configuration changed. Reset to apply it Now."); + StrCpyS (StringBuffer2, MAX_CHAR, L"Press ENTER to reset"); + // + // Popup a menu to notice user + // + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + FreePool (StringBuffer1); + FreePool (StringBuffer2); + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + } +} + +EFI_DEVICE_PATH * +FvFilePath ( + EFI_GUID *FileGuid + ) +{ + + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + return AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); +} + +/** + Launch Sovereign boot Wizard + + @retval TRUE Exit caller function. + @retval FALSE Not exit caller function. +**/ +EFI_STATUS +LaunchSovereignBootWizard ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + SOVEREIGN_BOOT_WIZARD_CONFIG_DATA SvBootData; + + FilePath = FvFilePath (&gSovereignBootWizardFormSetGuid); + if (FilePath == NULL) { + return EFI_NOT_FOUND; + } + + Status = EfiBootManagerInitializeLoadOption ( + &BootOption, + 0, + LoadOptionTypeBoot, + LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_APP, + L"Soverign Boot Wizard", + FilePath, + NULL, + 0 + ); + + if (!EFI_ERROR (Status)) { + // + // Since current no boot from removable media directly is allowed + // + gST->ConOut->ClearScreen (gST->ConOut); + // + // Check whether need to reset system. + // + SetupResetReminder (); + // + // Set the Sovereign Boot Wizard launch cause + // + SvBootData.AppLaunchCause = SV_BOOT_LAUNCH_VIA_SETUP; + gRT->SetVariable ( + SV_BOOT_DATA_VAR, + &gSovereignBootWizardFormSetGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (SOVEREIGN_BOOT_WIZARD_CONFIG_DATA), + &SvBootData + ); + + EfiBootManagerBoot (&BootOption); + // + // Remove the boot option after we return from the wizard + // + EfiBootManagerDeleteLoadOptionVariable (BootOption.OptionNumber, BootOption.OptionType); + + EfiBootManagerFreeLoadOption (&BootOption); + } + + return Status; +} + /** This function is called to provide results data to the driver. @@ -4949,6 +5160,34 @@ SecureBootCallback ( break; + case KEY_SOVEREIGN_BOOT_ENABLE: + Status = EFI_SUCCESS; + if (!Value->b) { + Status = gBS->LocateProtocol (&gEfiHiiPopupProtocolGuid, NULL, (VOID **)&HiiPopup); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = HiiPopup->CreatePopup ( + HiiPopup, + EfiHiiPopupStyleInfo, + EfiHiiPopupTypeYesNo, + Private->HiiHandle, + STRING_TOKEN (STR_SV_RESET_TO_DEFAULTS_POPUP), + &UserSelection + ); + if (UserSelection == EfiHiiPopupSelectionNo) { + // If the user decided not to disable Sovereign Boot, + // restore the enabled state and don't reset keys. + if (GetBrowserDataResult) { + Value->b = TRUE; + IfrNvData->SvBootEnable = TRUE; + } + } + } + + break; + case KEY_SECURE_BOOT_KEK_OPTION: case KEY_SECURE_BOOT_DB_OPTION: case KEY_SECURE_BOOT_DBX_OPTION: @@ -5478,6 +5717,30 @@ SecureBootCallback ( SecureBootExtractConfigFromVariable (Private, IfrNvData); } break; + } + case KEY_SOVEREIGN_BOOT_ENABLE: + { + Status = SaveSovereignBootVariable (Value->b); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + // If disabling, we need to restore Secure Boot keys + if (!Value->b) { + Status = KeyEnrollReset (IfrNvData); + + // + // Update secure boot strings after key reset + // + if (Status == EFI_SUCCESS) { + Status = UpdateSecureBootString (Private); + SecureBootExtractConfigFromVariable (Private, IfrNvData); + } + } + + break; + } + case KEY_LAUNCH_SOVEREIGN_BOOT_WIZARD: + { + Status = LaunchSovereignBootWizard (); + break; } default: break; @@ -5508,6 +5771,18 @@ SecureBootCallback ( } break; } + case KEY_SOVEREIGN_BOOT_ENABLE: { + Value->u8 = FixedPcdGetBool (PcdSovereignBootDefaultState); + if (EFI_ERROR (SaveSovereignBootVariable(Value->u8))) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Could not restore Sovereign Boot to default state!", + NULL + ); + } + break; + } default: break; } diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h index ff6e7301af..3480a8a108 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h @@ -19,6 +19,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include +#include #include #include @@ -35,6 +37,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -42,6 +45,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include "SecureBootConfigNvData.h" diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h index a5ed76b6f8..a576f70460 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h @@ -75,6 +75,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define KEY_SECURE_BOOT_DELETE_ALL_DATA 0x1110 #define KEY_SECURE_BOOT_DELETE_CHECK_DATA 0x1111 +#define KEY_SOVEREIGN_BOOT_ENABLE 0x1120 +#define KEY_LAUNCH_SOVEREIGN_BOOT_WIZARD 0x1121 + #define LABEL_KEK_DELETE 0x1200 #define LABEL_DB_DELETE 0x1201 #define LABEL_SIGNATURE_LIST_START 0x1202 @@ -138,6 +141,9 @@ typedef struct { UINT8 FileEnrollType; // File type of signature enroll UINT32 ListCount; // The count of signature list. UINT32 CheckedDataCount; // The count of checked signature data. + BOOLEAN SvBootAvailable; // If Sovereign Boot is enabled in the build and should be displayed + BOOLEAN SvBootEnable; // If Sovereign Boot flow should be enforced + BOOLEAN SvBootProvisioned; // If Sovereign Boot was already provisioned } SECUREBOOT_CONFIGURATION; #endif diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni index b1b00da832..93cb9dfa6c 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni @@ -27,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_SECURE_RESET_TO_DEFAULTS #language en-US "> Reset to default Secure Boot Keys" #string STR_RESET_TO_DEFAULTS_POPUP #language en-US "Secure Boot Keys & databases will be initialized from defaults.\n Are you sure?" +#string STR_SV_RESET_TO_DEFAULTS_POPUP #language en-US "Disabling Sovereign Boot will restore default Secure Boot Keys & databases.\n Are you sure?" #string STR_SECURE_ERASE_ALL_KEYS_HELP #language en-US "Erases all Secure Boot keys and leaves the related variables empty.\nYou will need to provision the keys to use Secure Boot again or reset the Secure Boot keys to defaults." #string STR_SECURE_ERASE_ALL_KEYS #language en-US "> Erase all Secure Boot Keys" @@ -159,3 +160,19 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_SIGNATURE_DATA_RSA_HASH_NAME_FORMAT #language en-US "RSA2048 SHA256 hash %g" #string STR_SIGNATURE_DELETE_ALL_CONFIRM #language en-US "Press 'Y' to delete all signature List." + +/* Sovereign Boot strings */ + +#string STR_SOVEREIGN_BOOT_OPTIONS #language en-US "*** Sovereign Boot Options ***" +#string STR_ENABLE_SOVEREIGN_BOOT_PROMPT #language en-US "Enable Sovereign Boot" +#string STR_ENABLE_SOVEREIGN_BOOT_HELP #language en-US "Enables/disables Sovereign Boot in the firmware boot flow. " + "When enabled, the firmware will invoke Sovereign Boot Wizard on the first boot, " + "or when defautl settings are restored (if Sovereign Boot is configured to be " + "enabled by default) or when UEFI Secure Boto fails to verify a boot image.\n\n" + "Sovereign Boot Wizard assist in configuring Secure Boot in an easy and " + "comprehensible way for less technical users.\n\n" + "If unsure, disable it, to use the default firmware keys and be able to boot " + "Windows and most common Linux distributions when Secure Boot is enabled." + +#string STR_LAUNCH_SOVEREIGN_BOOT_WIZARD_HELP #language en-US "Manually invoke Sovereign Boot Wizard to modify/augment the Sovereign Boot settings." +#string STR_LAUNCH_SOVEREIGN_BOOT_WIZARD_PROMPT #language en-US "> Launch Sovereign Boot Wizard" From 838daa7c221984aa8a2cac6914b40e2c2a32ffd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 26 Jun 2025 13:51:51 +0200 Subject: [PATCH 06/15] OvmfPkg/OvmfPkgX64: Build the SV Boot Wizard into FV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- OvmfPkg/OvmfPkgX64.dsc | 14 ++++++++++++-- OvmfPkg/OvmfPkgX64.fdf | 4 ++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index f9518cdd0a..0c9b48e46f 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -45,6 +45,7 @@ DEFINE OPAL_PASSWORD_ENABLE = TRUE DEFINE DASHARO_SYSTEM_FEATURES_ENABLE = TRUE DEFINE SETUP_PASSWORD_ENABLE = TRUE + DEFINE SOVEREIGN_BOOT_ENABLE = FALSE # # Network definition @@ -683,6 +684,12 @@ gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowDGPUPowerOption|FALSE gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable|0 + +!if $(SECURE_BOOT_ENABLE) == TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled|$(SOVEREIGN_BOOT_ENABLE) + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState|TRUE +!endif + ################################################################################ # # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform @@ -1053,8 +1060,6 @@ !endif !endif - DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf - # # Hash2 # @@ -1080,6 +1085,11 @@ SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf + +!if $(SOVEREIGN_BOOT_ENABLE) == TRUE + DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf +!endif + !endif OvmfPkg/PlatformDxe/Platform.inf diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index bff66aea14..390747c290 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -288,6 +288,10 @@ INF OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf INF SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf INF SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf +!if $(SOVEREIGN_BOOT_ENABLE) == TRUE + INF DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf +!endif + # gDefaultKEKFileGuid FILE FREEFORM = 6F64916E-9F7A-4C35-B952-CD041EFB05A3 { SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/MicCorKEKCA2011_2011-06-24.crt From d77494099dc8dcf9c1600052632782fea1a560ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Fri, 27 Jun 2025 14:16:57 +0200 Subject: [PATCH 07/15] SecurityPkg/VariableAuthenticated/SecureBootConfigDxe: Add SV Boot state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../SecureBootConfigDxe/SecureBootConfig.vfr | 16 +++ .../SecureBootConfigImpl.c | 112 +++++++++++++++++- .../SecureBootConfigNvData.h | 1 + .../SecureBootConfigStrings.uni | 7 ++ 4 files changed, 132 insertions(+), 4 deletions(-) diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr index 2ca5b88cfd..e88501b6df 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr @@ -83,6 +83,22 @@ formset flags = INTERACTIVE | RESET_REQUIRED, endcheckbox; + // Hidden checkbox for provisioned state, to be used in callback + // whe nefautl settigns are restored. + suppressif TRUE; + checkbox varid = SECUREBOOT_CONFIGURATION.SvBootProvisioned, + questionid = KEY_SOVEREIGN_BOOT_PROVISIONED, + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_PRIVISIONED_PROMPT), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_PRIVISIONED_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + endcheckbox; + endif; + + text + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_STATE_HELP), + text = STRING_TOKEN(STR_SOVEREIGN_BOOT_STATE_PROMPT), + text = STRING_TOKEN(STR_SOVEREIGN_BOOT_STATE_CONTENT); + disableif ideqval SECUREBOOT_CONFIGURATION.SvBootEnable == 0; subtitle text = STRING_TOKEN(STR_NULL); // diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index f2bc7a1574..8d5fb13da6 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -59,6 +59,7 @@ HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = { }; BOOLEAN mIsEnterSecureBootForm = FALSE; +BOOLEAN mResetSvBootState = FALSE; // // OID ASN.1 Value for Hash Algorithms @@ -301,7 +302,7 @@ SaveSecureBootVariable ( /** Set Sovereign Boot configuration into variable space. - @param[in] SvBootEnable The satte of Sovereign Boot. + @param[in] SvBootEnable The state of Sovereign Boot. @retval EFI_SUCCESS The operation is finished successfully. @retval Others Other errors as indicated. @@ -350,6 +351,53 @@ SaveSovereignBootVariable ( return Status; } +/** + Resets Sovereign Boot configuration and saves it into variable space. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +ResetSovereignBootState ( + SECUREBOOT_CONFIG_PRIVATE_DATA *Private + ) +{ + SOVEREIGN_BOOT_WIZARD_NV_CONFIG SvBootConfig; + EFI_STATUS Status; + UINT32 Attrs; + UINTN VarSize; + + VarSize = sizeof(SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + + Status = gRT->GetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + &Attrs, + &VarSize, + &SvBootConfig + ); + + if (EFI_ERROR (Status) || + Attrs != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS) || + VarSize != sizeof(SOVEREIGN_BOOT_WIZARD_NV_CONFIG) + ) { + SvBootConfig.SvBootEnabled = FixedPcdGetBool (PcdSovereignBootDefaultState); + } + + SvBootConfig.SvBootProvisioned = FALSE; + + Status = gRT->SetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG), + &SvBootConfig + ); + + return Status; +} + /** This code checks if the encode type and key strength of X.509 certificate is qualified. @@ -3602,6 +3650,12 @@ SecureBootExtractConfigFromVariable ( ConfigData->SvBootProvisioned = SvBootConfig->SvBootProvisioned; FreePool (SvBootConfig); } + + HiiSetString ( + Private->HiiHandle, + STRING_TOKEN (STR_SOVEREIGN_BOOT_STATE_CONTENT), + ConfigData->SvBootProvisioned ? L"Yes" : L"No", + NULL); } if (SecureBootEnable != NULL) { @@ -5125,6 +5179,21 @@ SecureBootCallback ( goto EXIT; } + if (Action == EFI_BROWSER_ACTION_SUBMITTED) { + Status = EFI_UNSUPPORTED; + if (QuestionId == KEY_SOVEREIGN_BOOT_PROVISIONED) { + Status = EFI_SUCCESS; + if (mResetSvBootState && !Value->b) { + Status = ResetSovereignBootState (Private); + if (GetBrowserDataResult) { + SecureBootExtractConfigFromVariable (Private, IfrNvData); + } + mResetSvBootState = FALSE; + } + } + goto EXIT; + } + if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE) && @@ -5683,6 +5752,16 @@ SecureBootCallback ( Status = KeyEnrollReset (IfrNvData); } + if (EFI_ERROR (Status)) { + return Status; + } + + // Resetting the keys need to reset the Sovereign Boot state + // as we will no longer have the trusted keys in db + if (FixedPcdGetBool (PcdSovereignBootEnabled)) { + Status = ResetSovereignBootState (Private); + } + // // Update secure boot strings after key reset // @@ -5709,6 +5788,17 @@ SecureBootCallback ( if (UserSelection == EfiHiiPopupSelectionYes) { Status = KeyEraseAll (); } + + if (EFI_ERROR (Status)) { + return Status; + } + + // Erasing the keys need to reset the Sovereign Boot state + // as we will no longer have the trusted keys in db + if (FixedPcdGetBool (PcdSovereignBootEnabled)) { + Status = ResetSovereignBootState (Private); + } + // // Update secure boot strings after key reset // @@ -5725,12 +5815,19 @@ SecureBootCallback ( // If disabling, we need to restore Secure Boot keys if (!Value->b) { Status = KeyEnrollReset (IfrNvData); - + if (EFI_ERROR (Status)) { + break; + } + // Reset the Sovereign Boot provisioning state + Status = ResetSovereignBootState (Private); + if (EFI_ERROR (Status)) { + break; + } // // Update secure boot strings after key reset // - if (Status == EFI_SUCCESS) { - Status = UpdateSecureBootString (Private); + Status = UpdateSecureBootString (Private); + if (GetBrowserDataResult) { SecureBootExtractConfigFromVariable (Private, IfrNvData); } } @@ -5783,6 +5880,13 @@ SecureBootCallback ( } break; } + case KEY_SOVEREIGN_BOOT_PROVISIONED: + { + Status = EFI_SUCCESS; + Value->b = FALSE; + mResetSvBootState = TRUE; + break; + } default: break; } diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h index a576f70460..fe7fb2dea0 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h @@ -77,6 +77,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define KEY_SOVEREIGN_BOOT_ENABLE 0x1120 #define KEY_LAUNCH_SOVEREIGN_BOOT_WIZARD 0x1121 +#define KEY_SOVEREIGN_BOOT_PROVISIONED 0x1122 #define LABEL_KEK_DELETE 0x1200 #define LABEL_DB_DELETE 0x1201 diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni index 93cb9dfa6c..5077c62528 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni @@ -176,3 +176,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_LAUNCH_SOVEREIGN_BOOT_WIZARD_HELP #language en-US "Manually invoke Sovereign Boot Wizard to modify/augment the Sovereign Boot settings." #string STR_LAUNCH_SOVEREIGN_BOOT_WIZARD_PROMPT #language en-US "> Launch Sovereign Boot Wizard" + +#string STR_SOVEREIGN_BOOT_PRIVISIONED_HELP #language en-US "Sovereign Boot provisioning state" +#string STR_SOVEREIGN_BOOT_PRIVISIONED_PROMPT #language en-US "Sovereign Boot Provisioned" + +#string STR_SOVEREIGN_BOOT_STATE_HELP #language en-US "Sovereign Boot provisioning state" +#string STR_SOVEREIGN_BOOT_STATE_PROMPT #language en-US "Sovereign Boot Provisioned" +#string STR_SOVEREIGN_BOOT_STATE_CONTENT #language en-US "Unknown" From b894c860fc91396031bd8efe5b3058278460296e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 26 Jun 2025 17:56:06 +0200 Subject: [PATCH 08/15] MdeModulePkg/BdsDxe,UefiBootManagerLib: Integrate SV Boot Wizard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../Include/Library/UefiBootManagerLib.h | 13 ++ .../Library/UefiBootManagerLib/BmBoot.c | 184 ++++++++++++++++-- .../Library/UefiBootManagerLib/InternalBm.h | 1 + .../UefiBootManagerLib/UefiBootManagerLib.inf | 6 + MdeModulePkg/Universal/BdsDxe/Bds.h | 5 + MdeModulePkg/Universal/BdsDxe/BdsDxe.inf | 6 + MdeModulePkg/Universal/BdsDxe/BdsEntry.c | 70 +++++++ .../SecureBootConfigImpl.c | 92 +-------- 8 files changed, 271 insertions(+), 106 deletions(-) diff --git a/MdeModulePkg/Include/Library/UefiBootManagerLib.h b/MdeModulePkg/Include/Library/UefiBootManagerLib.h index 34e217707e..aac2bb4693 100644 --- a/MdeModulePkg/Include/Library/UefiBootManagerLib.h +++ b/MdeModulePkg/Include/Library/UefiBootManagerLib.h @@ -813,4 +813,17 @@ EfiBootManagerDispatchDeferredImages ( VOID ); +/** + Launch Sovereign Boot Wizard + + @param AppLaunchCause The reason why wizard is beign launched. + + @retval EFI_SUCCESS The wizard successfully loaded and executed, + @retval Others The wizard not found or faield to launch. +**/ +EFI_STATUS +EfiBootManagerLaunchSovereignBootWizard ( + UINT8 AppLaunchCause + ); + #endif diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index e4559413c7..0ebbc3e34c 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -1821,6 +1821,123 @@ BmReportLoadFailure ( ); } +EFI_DEVICE_PATH * +FvFilePath ( + EFI_GUID *FileGuid + ) +{ + + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + return AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); +} + +/** + Launch Sovereign Boot Wizard + + @param AppLaunchCause The reason why wizard is beign launched. + + @retval EFI_SUCCESS The wizard successfully loaded and executed, + @retval Others The wizard not found or faield to launch. +**/ +EFI_STATUS +EfiBootManagerLaunchSovereignBootWizard ( + UINT8 AppLaunchCause + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + SOVEREIGN_BOOT_WIZARD_CONFIG_DATA SvBootData; + + if (!FixedPcdGetBool (PcdSovereignBootEnabled)) { + return EFI_NOT_FOUND; + } + + FilePath = FvFilePath (&gSovereignBootWizardFormSetGuid); + if (FilePath == NULL) { + return EFI_NOT_FOUND; + } + + Status = EfiBootManagerInitializeLoadOption ( + &BootOption, + 0, + LoadOptionTypeBoot, + LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_APP, + L"Soverign Boot Wizard", + FilePath, + NULL, + 0 + ); + + if (!EFI_ERROR (Status)) { + gST->ConOut->ClearScreen (gST->ConOut); + // + // Set the Sovereign Boot Wizard launch cause + // + SvBootData.AppLaunchCause = AppLaunchCause; + gRT->SetVariable ( + SV_BOOT_DATA_VAR, + &gSovereignBootWizardFormSetGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (SOVEREIGN_BOOT_WIZARD_CONFIG_DATA), + &SvBootData + ); + + EfiBootManagerBoot (&BootOption); + // + // Remove the boot option after we return from the wizard + // + EfiBootManagerDeleteLoadOptionVariable (BootOption.OptionNumber, BootOption.OptionType); + + EfiBootManagerFreeLoadOption (&BootOption); + } + + return Status; +} + +/** + Check if it's a Device Path pointing to Sovereign Boot Wizard. + + @param DevicePath Input device path. + + @retval TRUE The device path is Sovereign Boot Wizar File Device Path. + @retval FALSE The device path is NOT Sovereign Boot Wizar File Device Path. +**/ +BOOLEAN +BmIsSovereignBootWizardFilePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_HANDLE FvHandle; + VOID *NameGuid; + EFI_STATUS Status; + + Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle); + if (!EFI_ERROR (Status)) { + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevicePath); + if (NameGuid != NULL) { + return CompareGuid (NameGuid, &gSovereignBootWizardFormSetGuid); + } + } + + return FALSE; +} + + /** Attempt to boot the EFI boot option. This routine sets L"BootCurent" and also signals the EFI ready to boot event. If the device path for the option @@ -1847,21 +1964,26 @@ EfiBootManagerBoot ( IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption ) { - EFI_STATUS Status; - EFI_HANDLE ImageHandle; - EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; - UINT16 Uint16; - UINTN OptionNumber; - UINTN OriginalOptionNumber; - EFI_DEVICE_PATH_PROTOCOL *FilePath; - EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath; - VOID *FileBuffer; - UINTN FileSize; - EFI_BOOT_LOGO_PROTOCOL *BootLogo; - EFI_EVENT LegacyBootEvent; - EFI_INPUT_KEY Key; - UINTN Index; - UINT8 *SecureBoot; + EFI_STATUS Status; + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + UINT16 Uint16; + UINTN OptionNumber; + UINTN OriginalOptionNumber; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath; + VOID *FileBuffer; + UINTN FileSize; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + EFI_EVENT LegacyBootEvent; + EFI_INPUT_KEY Key; + UINTN Index; + UINT8 *SecureBoot; + UINTN SvBootConfigSize; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG *SvBootConfig; + BOOLEAN ScreenCleared; + + ScreenCleared = FALSE; if (BootOption == NULL) { return; @@ -2003,8 +2125,38 @@ EfiBootManagerBoot ( BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status); BootOption->Status = Status; + // Launch Sovereign Boot Wizard if image verification failed + if (Status == EFI_SECURITY_VIOLATION || Status == EFI_ACCESS_DENIED) { + // Launch it only if THe Sovereign Boto Wizard is enabeld in the build and + // we did not attempt to boot the wizard itself (safety check to avoid recursive loop) + if (FixedPcdGetBool (PcdSovereignBootEnabled) && !BmIsSovereignBootWizardFilePath (BootOption->FilePath)) { + + SvBootConfigSize = sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + GetVariable2 (SV_BOOT_CONFIG_VAR, &gSovereignBootWizardFormSetGuid, (VOID **)&SvBootConfig, &SvBootConfigSize); + + // Only if Sovereign Boot is provisioned. We should not end up in this path before provisioning + if ((SvBootConfig != NULL) && SvBootConfig->SvBootEnabled && SvBootConfig->SvBootProvisioned) { + Status = EfiBootManagerLaunchSovereignBootWizard (SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED); + if (EFI_ERROR (Status)) { + if (gST->ConOut != NULL) { + gST->ConOut->ClearScreen (gST->ConOut); + ScreenCleared = TRUE; + AsciiPrint ("The Sovereign Boot Wizard failed to launch or is missing!\n"); + } + } + } + + if (SvBootConfig != NULL) { + FreePool (SvBootConfig); + } + // If user did not trust the image or decided not to boot it, simply display the warning below as usual. + } + } + if (gST->ConOut != NULL) { - gST->ConOut->ClearScreen (gST->ConOut); + if (!ScreenCleared) { + gST->ConOut->ClearScreen (gST->ConOut); + } // // When UEFI Secure Boot is enabled, unsigned modules won't load. diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h index 48d3850b71..f17d6331e7 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h @@ -52,6 +52,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf index 2655d5c5e4..d19049a523 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf +++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf @@ -41,6 +41,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] HobLib @@ -87,6 +88,7 @@ gEfiDiskInfoSdMmcInterfaceGuid ## SOMETIMES_CONSUMES ## GUID gEfiDiskInfoUfsInterfaceGuid ## SOMETIMES_CONSUMES ## GUID gEfiPartTypeSystemPartGuid ## CONSUMES ## GUID + gSovereignBootWizardFormSetGuid ## SOMETIMES_CONSUMES [Protocols] gEfiPciRootBridgeIoProtocolGuid ## CONSUMES @@ -123,3 +125,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMaxRepairCount ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCreatePreInstalledBootOptions ## CONSUMES + +[FixedPcd] + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState diff --git a/MdeModulePkg/Universal/BdsDxe/Bds.h b/MdeModulePkg/Universal/BdsDxe/Bds.h index 2b20fec8f4..2055564734 100644 --- a/MdeModulePkg/Universal/BdsDxe/Bds.h +++ b/MdeModulePkg/Universal/BdsDxe/Bds.h @@ -14,6 +14,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include + +#include +#include #include #include @@ -22,6 +26,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include #include diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf index 78e2e811a2..f3b2f60f1e 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +++ b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf @@ -55,6 +55,7 @@ PlatformBootManagerLib PcdLib PrintLib + HobLib [Guids] gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootNext" (The number of next boot option) @@ -77,6 +78,7 @@ gEfiEventReadyToBootGuid ## CONSUMES ## Event gDasharoSystemFeaturesGuid ## CONSUMES ## Variable:L"QuietBoot" ## CONSUMES ## Variable:L"FastBoot" + gSovereignBootWizardFormSetGuid ## SOMETIMES_CONSUMES ## Variable:L"SvBootConfig" [Protocols] gEfiBdsArchProtocolGuid ## PRODUCES @@ -105,6 +107,10 @@ gEfiMdePkgTokenSpaceGuid.PcdFastBootFeatureEnabled ## CONSUMES gEfiMdePkgTokenSpaceGuid.PcdQuietBootFeatureEnabled ## CONSUMES +[FixedPcd] + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState + [Depex] TRUE diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c index 29fed73ca8..a6eb8153c9 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c @@ -720,6 +720,11 @@ BdsEntry ( EFI_STATUS BootManagerMenuStatus; EFI_BOOT_MANAGER_LOAD_OPTION PlatformDefaultBootOption; BOOLEAN PlatformDefaultBootOptionValid; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG SvBootConfig; + UINTN SvBootConfigSize; + EFI_BOOT_MODE BootMode; + EFI_INPUT_KEY Key; + UINTN KeyIndex; HotkeyTriggered = NULL; Status = EFI_SUCCESS; @@ -1098,6 +1103,71 @@ BdsEntry ( EfiBootManagerBoot (&BootManagerMenu); } + // Check Boot Mode + BootMode = GetBootModeHob (); + + if (FixedPcdGetBool (PcdSovereignBootEnabled) && BootMode != BOOT_ON_FLASH_UPDATE) { + SvBootConfigSize = sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + Status = gRT->GetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + NULL, + &SvBootConfigSize, + (VOID *)&SvBootConfig + ); + + if (EFI_ERROR (Status)) { + SvBootConfig.SvBootEnabled = FixedPcdGetBool (PcdSovereignBootDefaultState); + SvBootConfig.SvBootProvisioned = FALSE; + } + + // Handle Invalid state. Sovereign Boot cannot be provisioned when disabled. + if (!SvBootConfig.SvBootEnabled && SvBootConfig.SvBootProvisioned) { + SvBootConfig.SvBootProvisioned = FALSE; + SvBootConfigSize = sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + gRT->SetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + SvBootConfigSize, + (VOID *)&SvBootConfig + ); + } + + // Only if Sovereing Boot is NOT provisioned or settings has been reset (booting for the first time too) + if (SvBootConfig.SvBootEnabled) { + if (!SvBootConfig.SvBootProvisioned || + BootMode == BOOT_WITH_DEFAULT_SETTINGS || + BootMode == BOOT_WITH_MFG_MODE_SETTINGS) + { + Status = EfiBootManagerLaunchSovereignBootWizard (SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS); + if (EFI_ERROR (Status)) { + if (gST->ConOut != NULL) { + gST->ConOut->ClearScreen (gST->ConOut); + AsciiPrint ( + "Booting Sovereign Boot Wizard failed due to '%r'.\n" + "Press any key to continue...\n", + Status); + } + if (gST->ConIn != NULL) { + Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &KeyIndex); + ASSERT_EFI_ERROR (Status); + ASSERT (KeyIndex == 0); + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {} + } + } + + if (BootManagerMenuStatus != EFI_NOT_FOUND) { + // Boot to Boot Manager Menu/Setup upon Sovereign Boot Wizard exit/failure. + // The Wizard should always boot after provisionign is finished, + // unless there are no Sovereign Boot compatible boot options detected, + // then we still have to fallback to setup. + EfiBootManagerBoot (&BootManagerMenu); + } + } + } + } + if (!PlatformRecovery) { // // Execute SysPrep#### diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index 8d5fb13da6..35a8baf089 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -4901,95 +4901,6 @@ SetupResetReminder ( } } -EFI_DEVICE_PATH * -FvFilePath ( - EFI_GUID *FileGuid - ) -{ - - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; - - EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); - - Status = gBS->HandleProtocol ( - gImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **) &LoadedImage - ); - ASSERT_EFI_ERROR (Status); - return AppendDevicePathNode ( - DevicePathFromHandle (LoadedImage->DeviceHandle), - (EFI_DEVICE_PATH_PROTOCOL *) &FileNode - ); -} - -/** - Launch Sovereign boot Wizard - - @retval TRUE Exit caller function. - @retval FALSE Not exit caller function. -**/ -EFI_STATUS -LaunchSovereignBootWizard ( - VOID - ) -{ - EFI_STATUS Status; - EFI_BOOT_MANAGER_LOAD_OPTION BootOption; - EFI_DEVICE_PATH_PROTOCOL *FilePath; - SOVEREIGN_BOOT_WIZARD_CONFIG_DATA SvBootData; - - FilePath = FvFilePath (&gSovereignBootWizardFormSetGuid); - if (FilePath == NULL) { - return EFI_NOT_FOUND; - } - - Status = EfiBootManagerInitializeLoadOption ( - &BootOption, - 0, - LoadOptionTypeBoot, - LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_APP, - L"Soverign Boot Wizard", - FilePath, - NULL, - 0 - ); - - if (!EFI_ERROR (Status)) { - // - // Since current no boot from removable media directly is allowed - // - gST->ConOut->ClearScreen (gST->ConOut); - // - // Check whether need to reset system. - // - SetupResetReminder (); - // - // Set the Sovereign Boot Wizard launch cause - // - SvBootData.AppLaunchCause = SV_BOOT_LAUNCH_VIA_SETUP; - gRT->SetVariable ( - SV_BOOT_DATA_VAR, - &gSovereignBootWizardFormSetGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS, - sizeof (SOVEREIGN_BOOT_WIZARD_CONFIG_DATA), - &SvBootData - ); - - EfiBootManagerBoot (&BootOption); - // - // Remove the boot option after we return from the wizard - // - EfiBootManagerDeleteLoadOptionVariable (BootOption.OptionNumber, BootOption.OptionType); - - EfiBootManagerFreeLoadOption (&BootOption); - } - - return Status; -} - /** This function is called to provide results data to the driver. @@ -5836,7 +5747,8 @@ SecureBootCallback ( } case KEY_LAUNCH_SOVEREIGN_BOOT_WIZARD: { - Status = LaunchSovereignBootWizard (); + SetupResetReminder (); + Status = EfiBootManagerLaunchSovereignBootWizard (SV_BOOT_LAUNCH_VIA_SETUP); break; } default: From 40b315ad640ecd3622e4b4fbf31fd4da6a829e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 26 Jun 2025 17:57:30 +0200 Subject: [PATCH 09/15] OvmfPkg/PlatformBootManagerLib: Skip printing hotkeys in SV Boot path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../PlatformBootManagerLib/BdsPlatform.c | 37 ++++++++++++++++--- .../PlatformBootManagerLib.inf | 5 +++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c index 6b1408f68c..0ad9bce0ac 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -173,7 +173,7 @@ FileIsInFv ( } EFI_DEVICE_PATH * -FvFilePath ( +BdsFvFilePath ( EFI_GUID *FileGuid ) { @@ -221,7 +221,7 @@ RegisterBootManagerMenuAppBootOption ( EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN OptionNumber; - DevicePath = FvFilePath (FileGuid); + DevicePath = BdsFvFilePath (FileGuid); Status = EfiBootManagerInitializeLoadOption ( &NewOption, LoadOptionNumberUnassigned, @@ -2092,14 +2092,39 @@ PlatformBootManagerAfterConsole ( BOOLEAN NetBootEnabled; UINTN VarSize; EFI_STATUS Status; + UINTN SvBootConfigSize; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG SvBootConfig; DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n")); + if (FixedPcdGetBool (PcdSovereignBootEnabled)) { + SvBootConfigSize = sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + Status = gRT->GetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + NULL, + &SvBootConfigSize, + (VOID *)&SvBootConfig + ); + + if (EFI_ERROR (Status)) { + SvBootConfig.SvBootEnabled = FixedPcdGetBool (PcdSovereignBootDefaultState); + SvBootConfig.SvBootProvisioned = FALSE; + } + } else { + SvBootConfig.SvBootEnabled = FALSE; + SvBootConfig.SvBootProvisioned = FALSE; + } + // This is probably the earliest we can print this, as before the console is - // not ready yet. - Print(L"F2 to enter Setup\n"); - Print(L"ESC to enter Boot Manager Menu\n"); - Print(L"ENTER to boot directly\n"); + // not ready yet. Don't print the hotkeys if SvBoot is enabled but not yet + // provisioned. We won't be able to use the hotkeys anyways in that case. + if (!SvBootConfig.SvBootEnabled || + (SvBootConfig.SvBootEnabled && SvBootConfig.SvBootProvisioned)) { + Print(L"F2 to enter Setup\n"); + Print(L"ESC to enter Boot Manager Menu\n"); + Print(L"ENTER to boot directly\n"); + } if (PcdGetBool (PcdOvmfFlashVariablesEnable)) { DEBUG (( diff --git a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index 54d5e6c91d..687d7b9a1c 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -75,6 +75,10 @@ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity ## CONSUMES gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits ## CONSUMES +[FixedPcd] + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState + [Pcd.IA32, Pcd.X64] gEfiMdePkgTokenSpaceGuid.PcdFSBClock @@ -95,3 +99,4 @@ gGrubFileGuid gEfiTtyTermGuid gDasharoSystemFeaturesGuid + gSovereignBootWizardFormSetGuid From 17b7ba66c4c8203275edc54e8c73c1a11b808ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Fri, 27 Jun 2025 15:06:13 +0200 Subject: [PATCH 10/15] DasharoPayloadPkg/PlatformBootManagerLib/: Skip printing hotkeys in SV Boot path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../PlatformBootManager.c | 54 +++++++++++++------ .../PlatformBootManager.h | 2 + .../PlatformBootManagerLib.inf | 3 ++ 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c index 4586f44ae4..10372bbf1e 100644 --- a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c @@ -312,7 +312,7 @@ SyncFvBootOption ( } EFI_DEVICE_PATH * -FvFilePath ( +BdsFvFilePath ( EFI_GUID *FileGuid ) { @@ -351,7 +351,7 @@ RegisterBootManagerMenuAppBootOption ( EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN OptionNumber; - DevicePath = FvFilePath (&mBootMenuFile); + DevicePath = BdsFvFilePath (&mBootMenuFile); // Use LOAD_OPTION_HIDDEN to not display Boot Manager Menu App in // "One Time Boot" menu. Status = EfiBootManagerInitializeLoadOption ( @@ -396,7 +396,7 @@ UnregisterBootManagerMenuAppBootOption ( INTN OptionIndex; EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; - DevicePath = FvFilePath (&mBootMenuFile); + DevicePath = BdsFvFilePath (&mBootMenuFile); // Use LOAD_OPTION_HIDDEN to not display Boot Manager Menu App in // "One Time Boot" menu. Status = EfiBootManagerInitializeLoadOption ( @@ -1711,17 +1711,18 @@ PlatformBootManagerAfterConsole ( VOID ) { - EFI_STATUS Status; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; - EFI_GRAPHICS_OUTPUT_BLT_PIXEL White; - CHAR16 *BootMenuKey; - CHAR16 *SetupMenuKey; - BOOLEAN NetBootEnabled; - BOOLEAN FUMEnabled; - BOOLEAN BootMenuEnable; - UINTN VarSize; - EFI_EVENT Event; - EFI_INPUT_KEY Enter; + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL White; + CHAR16 *BootMenuKey; + CHAR16 *SetupMenuKey; + BOOLEAN NetBootEnabled; + BOOLEAN FUMEnabled; + BOOLEAN BootMenuEnable; + UINTN VarSize; + EFI_EVENT Event; + EFI_INPUT_KEY Enter; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG SvBootConfig; Black.Blue = Black.Green = Black.Red = Black.Reserved = 0; White.Blue = White.Green = White.Red = White.Reserved = 0xFF; @@ -1872,9 +1873,32 @@ PlatformBootManagerAfterConsole ( Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + if (FixedPcdGetBool (PcdSovereignBootEnabled)) { + VarSize = sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG); + Status = gRT->GetVariable ( + SV_BOOT_CONFIG_VAR, + &gSovereignBootWizardFormSetGuid, + NULL, + &VarSize, + (VOID *)&SvBootConfig + ); + + if (EFI_ERROR (Status)) { + SvBootConfig.SvBootEnabled = FixedPcdGetBool (PcdSovereignBootDefaultState); + SvBootConfig.SvBootProvisioned = FALSE; + } + } else { + SvBootConfig.SvBootEnabled = FALSE; + SvBootConfig.SvBootProvisioned = FALSE; + } + // Print the prompt and SOL strings only if Quiet Boot and Fast Boot are disabled. // Do not refresh the logo, it should stay intact. - if (!mFastBoot && !mQuietBoot) { + // Don't print the hotkeys if SvBoot is enabled but not yet + // provisioned. We won't be able to use the hotkeys anyways in that case. + if (!mFastBoot && !mQuietBoot && + (!SvBootConfig.SvBootEnabled || + (SvBootConfig.SvBootEnabled && SvBootConfig.SvBootProvisioned))) { if (PcdGetBool (PcdPrintSolStrings)) PrintSolStrings(); diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h index 9b181b8fd9..0ec80863e4 100644 --- a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h @@ -14,6 +14,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include +#include + #include #include #include diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index f5a9aca1bf..8b338f0d15 100644 --- a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -73,6 +73,7 @@ gEdkiiSCOTermGuid gEfiPcAnsiGuid gDasharoSystemFeaturesGuid + gSovereignBootWizardFormSetGuid [Protocols] gEfiGenericMemTestProtocolGuid ## CONSUMES @@ -115,3 +116,5 @@ gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirection2DefaultState gDasharoSystemFeaturesTokenSpaceGuid.PcdHave2ndUart gDasharoSystemFeaturesTokenSpaceGuid.PcdFumAutoIpxeBoot + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState From 2d076b589e5cc8e1525080c9ac77646c5c8dc978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Fri, 27 Jun 2025 15:06:28 +0200 Subject: [PATCH 11/15] MdeModulePkg/Universal/BdsDxe/BdsEntry.c: Add debug prints for SV Boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- MdeModulePkg/Universal/BdsDxe/BdsEntry.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c index a6eb8153c9..aa17cdebc3 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c @@ -1134,12 +1134,16 @@ BdsEntry ( ); } + DEBUG ((EFI_D_INFO, "Sovereign Boot Wizard state:\n\tEnabled: %d\n\tProvisioned %d\n", + SvBootConfig.SvBootEnabled, SvBootConfig.SvBootProvisioned)); + // Only if Sovereing Boot is NOT provisioned or settings has been reset (booting for the first time too) if (SvBootConfig.SvBootEnabled) { if (!SvBootConfig.SvBootProvisioned || BootMode == BOOT_WITH_DEFAULT_SETTINGS || BootMode == BOOT_WITH_MFG_MODE_SETTINGS) { + DEBUG ((EFI_D_INFO, "Sovereign Boot: System is not provisioned or boots with default settings. Launching Wizard...\n")); Status = EfiBootManagerLaunchSovereignBootWizard (SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS); if (EFI_ERROR (Status)) { if (gST->ConOut != NULL) { From 35dff39ee040b4e3979ca9f6974bc1c1039fcd1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Fri, 27 Jun 2025 15:21:33 +0200 Subject: [PATCH 12/15] DasharoPayloadPkg: Integrate Sovereign Boot Wizard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- DasharoPayloadPkg/DasharoPayloadPkg.dsc | 9 +++++++++ DasharoPayloadPkg/DasharoPayloadPkg.fdf | 3 +++ 2 files changed, 12 insertions(+) diff --git a/DasharoPayloadPkg/DasharoPayloadPkg.dsc b/DasharoPayloadPkg/DasharoPayloadPkg.dsc index 87650bd0c7..9bfb1c3b7e 100644 --- a/DasharoPayloadPkg/DasharoPayloadPkg.dsc +++ b/DasharoPayloadPkg/DasharoPayloadPkg.dsc @@ -116,6 +116,7 @@ DEFINE CAPSULE_SUPPORT = FALSE DEFINE CAPSULE_MAIN_FW_GUID = DEFINE GRAPHICAL_CAPSULE_PROGRESS = TRUE + DEFINE SOVEREIGN_BOOT_ENABLE = FALSE # # Network definition @@ -542,6 +543,11 @@ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrd gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable|0 !endif +!if $(SECURE_BOOT_ENABLE) == TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootEnabled|$(SOVEREIGN_BOOT_ENABLE) + gDasharoSystemFeaturesTokenSpaceGuid.PcdSovereignBootDefaultState|TRUE +!endif + !if $(SOURCE_DEBUG_ENABLE) gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2 !endif @@ -776,6 +782,9 @@ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrd SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf +!if $(SOVEREIGN_BOOT_ENABLE) == TRUE + DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf +!endif !endif !if $(SETUP_PASSWORD_ENABLE) == TRUE diff --git a/DasharoPayloadPkg/DasharoPayloadPkg.fdf b/DasharoPayloadPkg/DasharoPayloadPkg.fdf index 3d921f53fd..3f28bd6cb3 100644 --- a/DasharoPayloadPkg/DasharoPayloadPkg.fdf +++ b/DasharoPayloadPkg/DasharoPayloadPkg.fdf @@ -283,6 +283,9 @@ INF SecurityPkg/Pkcs7Verify/Pkcs7VerifyDxe/Pkcs7VerifyDxe.inf INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf INF SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf INF SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf +!if $(SOVEREIGN_BOOT_ENABLE) == TRUE + INF DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf +!endif # gDefaultKEKFileGuid FILE FREEFORM = 6F64916E-9F7A-4C35-B952-CD041EFB05A3 { From 89b3739fbe52c760f3d2815f42d621c391c501e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Fri, 27 Jun 2025 16:25:36 +0200 Subject: [PATCH 13/15] DasharoModulePkg/Application/SovereignBootWizard: Display launch reasons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- .../SovereignBootWizard/SovereignBootWizard.c | 44 ++++++++++++++++--- .../SovereignBootWizardVfr.vfr | 12 ++++- .../SovereignBootWizardVfrStrings.uni | 22 +++++++--- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c index 01e632d4b0..d4df2a138f 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c @@ -457,6 +457,7 @@ SovereignBootWizardInit ( EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; CHAR16 *NewString; EFI_HANDLE AppHandle; + EFI_FORM_ID FormId; NewString = NULL; AppHandle = NULL; @@ -630,9 +631,9 @@ SovereignBootWizardInit ( ConfigData->AppLaunchCause = SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS; } } else { - // If not provisioned, the launch cause can only be undefined or boot with defaults + // If not provisioned, the launch cause can not be verification failure if (!SvConfig->SvBootProvisioned && - ConfigData->AppLaunchCause >= SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) + ConfigData->AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) { ConfigData->AppLaunchCause = SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS; } @@ -643,6 +644,31 @@ SovereignBootWizardInit ( ConfigData->AppLaunchCause = SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS; } + switch (ConfigData->AppLaunchCause) { + case SV_BOOT_LAUNCH_BOOT_WITH_DEFAULT_SETTINGS: + NewString = HiiGetString(HiiHandle, STRING_TOKEN (STR_LAUNCH_CAUSE_DEFAULT_SETTINGS), NULL); + break; + case SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED: + // Override the "do not trust key" to avoid displaying "next bootloader" + NewString = HiiGetString(HiiHandle, STRING_TOKEN (STR_DO_NOT_TRUST_KEY2), NULL); + if (NewString != NULL) { + HiiSetString(HiiHandle, STRING_TOKEN (STR_DO_NOT_TRUST_KEY), NewString, NULL); + } + + NewString = HiiGetString(HiiHandle, STRING_TOKEN (STR_LAUNCH_CAUSE_VERIFICATION_FAILED), NULL); + break; + case SV_BOOT_LAUNCH_VIA_SETUP: + NewString = HiiGetString(HiiHandle, STRING_TOKEN (STR_LAUNCH_CAUSE_SETUP), NULL); + break; + default: + NewString = NULL; + break; + } + + if (NewString != NULL) { + HiiSetString(HiiHandle, STRING_TOKEN (STR_LAUNCH_REASON), NewString, NULL); + } + // // Override Hotkeys, F9 and F10 won't be needed by this application // @@ -655,6 +681,16 @@ SovereignBootWizardInit ( FormBrowserEx2->RegisterHotKey (&HotKey, 0, 0, NULL); } + if (SvConfig->SvBootProvisioned) { + if (ConfigData->AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) { + FormId = SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID; + } else { + FormId = SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID; + } + } else { + FormId = SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID; + } + // // turn off the watchdog timer // @@ -666,9 +702,7 @@ SovereignBootWizardInit ( &HiiHandle, 1, &gSovereignBootWizardFormSetGuid, - SvConfig->SvBootProvisioned ? - SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID : - SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID, + FormId, NULL, NULL ); diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr index 487b676f52..e9c65e1f87 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr @@ -43,6 +43,9 @@ formset title = STRING_TOKEN(STR_FORM1_TITLE); subtitle text = STRING_TOKEN(STR_WELCOME_SUBTITLE); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_LAUNCH_REASON); + subtitle text = STRING_TOKEN(STR_WELCOME_PROMPT); // Empty text field so that none of the options are // highlighted/selected by default. @@ -92,8 +95,13 @@ formset form formid = SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, title = STRING_TOKEN(STR_FORM2_TITLE); + disableif ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; subtitle text = STRING_TOKEN(STR_CONFIG_SUBTITLE); subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + endif; + disableif NOT ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; + subtitle text = STRING_TOKEN(STR_LAUNCH_REASON); + endif; subtitle text = STRING_TOKEN(STR_BOOTOPT_DESCRIPTION); subtitle text = STRING_TOKEN(STR_HW_PATH); @@ -118,11 +126,13 @@ formset flags = INTERACTIVE, key = TRUST_KEY_AND_BOOT_FORM2_QUESTION_ID; + disableif ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; text help = STRING_TOKEN(STR_EMPTY_STRING), text = STRING_TOKEN(STR_TRUST_KEY), flags = INTERACTIVE, key = TRUST_KEY_FORM2_QUESTION_ID; + endif; text help = STRING_TOKEN(STR_EMPTY_STRING), @@ -153,8 +163,8 @@ formset title = STRING_TOKEN(STR_FORM9_TITLE); subtitle text = STRING_TOKEN(STR_INTERACTIVE_MODE_SUBTITLE); - subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_LAUNCH_REASON); text help = STRING_TOKEN(STR_EMPTY_STRING), diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni index 2e2b8f8e13..a1700eb372 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni @@ -28,10 +28,19 @@ #string FUNCTION_NINE_STRING #language en-US "F9=Reset to Defaults" #string FUNCTION_TEN_STRING #language en-US "F10=Save" + +// Application launch causes +#string STR_LAUNCH_REASON #language en-US "\n" +#string STR_LAUNCH_CAUSE_DEFAULT_SETTINGS #language en-US "You see this window because you are booting for the first time or restored default system settings.\n\n" +#string STR_LAUNCH_CAUSE_SETUP #language en-US "You see this window because you have explicitly requested to launch the Wizard via system setup.\n" + "If you ended up here by mistake, please exit the application to avoid making changes to your system configuration.\n\n" +#string STR_LAUNCH_CAUSE_VERIFICATION_FAILED #language en-US "You see this window because the system attempted to boot an untrusted image.\n\n" + // Welcome page strings #string STR_FORM1_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_WELCOME_SUBTITLE #language en-US "Welcome to Sovereign Boot Provisioning Wizard!\n\n" - "Please select the UEFI Secure Boot scheme you would like to use:" +#string STR_WELCOME_SUBTITLE #language en-US "Welcome to Sovereign Boot Provisioning Wizard!\n" +#string STR_WELCOME_PROMPT #language en-US "The Wizard will assist in setting up the UEFI Secure Boot feature. " + "Please select the UEFI Secure Boot scheme you would like to use:\n" #string STR_SELECT_SOVEREIGN_BOOT #language en-US "Sovereign Boot" #string STR_SELECT_SOVEREIGN_BOOT_HELP #language en-US "" @@ -42,12 +51,12 @@ #string STR_SELECT_DEFAULT_SECURE_BOOT_HELP #language en-US "" #string STR_MS_SECURE_BOOT_FEATURES #language en-US "* Trust firmware's default certificates\n" "* Compatible with common operating systems\n" - "* Does not modify current Secure Boot settings" + "* Enrolls firmware's default Secure Boot keys" // Configuration page strings #string STR_FORM2_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_CONFIG_SUBTITLE #language en-US "A new bootloader key has been detected." +#string STR_CONFIG_SUBTITLE #language en-US "A new bootloader/key has been detected." #string STR_BOOTOPT_DESCRIPTION #language en-US "Description: " #string STR_HW_PATH #language en-US "Hardware path: " @@ -57,8 +66,9 @@ #string STR_TRUST_QUESTION #language en-US "Do you want to trust this key/image and continue booting?" #string STR_DO_NOT_TRUST_KEY #language en-US "[Do NOT trust, next key/bootloader]" -#string STR_TRUST_KEY_AND_BOOT #language en-US "[Trust this key and boot]" -#string STR_TRUST_KEY #language en-US "[Trust this key, next key/bootloader]" +#string STR_DO_NOT_TRUST_KEY2 #language en-US "[Do NOT trust]" +#string STR_TRUST_KEY_AND_BOOT #language en-US "[Trust this key/image and boot]" +#string STR_TRUST_KEY #language en-US "[Trust this key/image, next key/bootloader]" #string STR_SHOW_KEY_DETAILS #language en-US "[Show key/certificate details]" // Interactive mode strings From 676f9148c18b424e3c458b7a4b9490f6683187b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 3 Jul 2025 09:53:36 +0200 Subject: [PATCH 14/15] Fix typos after review Co-authored-by: SergiiDmytruk --- DasharoModulePkg/Include/Guid/SovereignBoot.h | 2 +- MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 2 +- .../SecureBootConfigDxe/SecureBootConfig.vfr | 2 +- .../SecureBootConfigDxe/SecureBootConfigStrings.uni | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DasharoModulePkg/Include/Guid/SovereignBoot.h b/DasharoModulePkg/Include/Guid/SovereignBoot.h index e3c2d5b4e3..e84eaeae48 100644 --- a/DasharoModulePkg/Include/Guid/SovereignBoot.h +++ b/DasharoModulePkg/Include/Guid/SovereignBoot.h @@ -19,7 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent // Application launch causes. Determine the logic and screens showed // when the application is launched. // We want different screens and messages when: -// 1. SV Boot is proviosioned by image fails to verify. +// 1. SV Boot is provisioned but image fails to verify. // 2. SV Boot is not yet provisioned or platform booting with default settings. // 3. Application is launched from setup #define SV_BOOT_LAUNCH_UNDEFINED 0 diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index 0ebbc3e34c..016a0dad80 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -1877,7 +1877,7 @@ EfiBootManagerLaunchSovereignBootWizard ( 0, LoadOptionTypeBoot, LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_APP, - L"Soverign Boot Wizard", + L"Sovereign Boot Wizard", FilePath, NULL, 0 diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr index e88501b6df..85517ac8c6 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr @@ -84,7 +84,7 @@ formset endcheckbox; // Hidden checkbox for provisioned state, to be used in callback - // whe nefautl settigns are restored. + // when default settings are restored. suppressif TRUE; checkbox varid = SECUREBOOT_CONFIGURATION.SvBootProvisioned, questionid = KEY_SOVEREIGN_BOOT_PROVISIONED, diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni index 5077c62528..43b4dc4a00 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni @@ -167,9 +167,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_ENABLE_SOVEREIGN_BOOT_PROMPT #language en-US "Enable Sovereign Boot" #string STR_ENABLE_SOVEREIGN_BOOT_HELP #language en-US "Enables/disables Sovereign Boot in the firmware boot flow. " "When enabled, the firmware will invoke Sovereign Boot Wizard on the first boot, " - "or when defautl settings are restored (if Sovereign Boot is configured to be " - "enabled by default) or when UEFI Secure Boto fails to verify a boot image.\n\n" - "Sovereign Boot Wizard assist in configuring Secure Boot in an easy and " + "or when default settings are restored (if Sovereign Boot is configured to be " + "enabled by default) or when UEFI Secure Boot fails to verify a boot image.\n\n" + "Sovereign Boot Wizard assists in configuring Secure Boot in an easy and " "comprehensible way for less technical users.\n\n" "If unsure, disable it, to use the default firmware keys and be able to boot " "Windows and most common Linux distributions when Secure Boot is enabled." From 008ea3ad95d299fe4ebbd99cb3dd985378f35aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 3 Jul 2025 10:07:05 +0200 Subject: [PATCH 15/15] treewide: Pass string literals in SetupResetReminder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski --- MdeModulePkg/Application/UiApp/FrontPage.c | 18 ++++++------------ .../BootMaintenanceManagerUiLib/BootOption.c | 18 ++++++------------ .../Library/BootManagerUiLib/BootManager.c | 18 ++++++------------ .../SecureBootConfigDxe/SecureBootConfigImpl.c | 18 ++++++------------ 4 files changed, 24 insertions(+), 48 deletions(-) diff --git a/MdeModulePkg/Application/UiApp/FrontPage.c b/MdeModulePkg/Application/UiApp/FrontPage.c index f2015ea742..0680fa00da 100644 --- a/MdeModulePkg/Application/UiApp/FrontPage.c +++ b/MdeModulePkg/Application/UiApp/FrontPage.c @@ -1132,29 +1132,23 @@ SetupResetReminder ( ) { EFI_INPUT_KEY Key; - CHAR16 *StringBuffer1; - CHAR16 *StringBuffer2; // // check any reset required change is applied? if yes, reset system // if (IsResetRequired ()) { - StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); - ASSERT (StringBuffer1 != NULL); - StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); - ASSERT (StringBuffer2 != NULL); - StrCpyS (StringBuffer1, MAX_STRING_LEN, L"Configuration changed. Reset to apply it Now."); - StrCpyS (StringBuffer2, MAX_STRING_LEN, L"Press ENTER to reset"); // // Popup a menu to notice user // do { - CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Configuration changed. Reset to apply it Now.", + L"Press ENTER to reset", + NULL); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - FreePool (StringBuffer1); - FreePool (StringBuffer2); - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } } diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c index e22aaf3039..1d592f98e6 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c @@ -28,8 +28,6 @@ BmmSetupResetReminder ( ) { EFI_INPUT_KEY Key; - CHAR16 *StringBuffer1; - CHAR16 *StringBuffer2; EFI_STATUS Status; EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2; @@ -42,22 +40,18 @@ BmmSetupResetReminder ( // check any reset required change is applied? if yes, reset system // if (!EFI_ERROR (Status) && FormBrowserEx2->IsResetRequired ()) { - StringBuffer1 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16)); - ASSERT (StringBuffer1 != NULL); - StringBuffer2 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16)); - ASSERT (StringBuffer2 != NULL); - StrCpyS (StringBuffer1, MAX_CHAR, L"Configuration changed. Reset to apply it Now."); - StrCpyS (StringBuffer2, MAX_CHAR, L"Press ENTER to reset"); // // Popup a menu to notice user // do { - CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Configuration changed. Reset to apply it Now.", + L"Press ENTER to reset", + NULL); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - FreePool (StringBuffer1); - FreePool (StringBuffer2); - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } } diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c index 5ceb54164d..55f6fc148a 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c @@ -305,8 +305,6 @@ BmSetupResetReminder ( ) { EFI_INPUT_KEY Key; - CHAR16 *StringBuffer1; - CHAR16 *StringBuffer2; EFI_STATUS Status; EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2; @@ -318,22 +316,18 @@ BmSetupResetReminder ( // check any reset required change is applied? if yes, reset system // if (!EFI_ERROR (Status) && FormBrowserEx2->IsResetRequired ()) { - StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); - ASSERT (StringBuffer1 != NULL); - StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); - ASSERT (StringBuffer2 != NULL); - StrCpyS (StringBuffer1, MAX_STRING_LEN, L"Configuration changed. Reset to apply it Now."); - StrCpyS (StringBuffer2, MAX_STRING_LEN, L"Press ENTER to reset"); // // Popup a menu to notice user // do { - CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Configuration changed. Reset to apply it Now.", + L"Press ENTER to reset", + NULL); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - FreePool (StringBuffer1); - FreePool (StringBuffer2); - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } } diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index 35a8baf089..e33df6842e 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -4867,8 +4867,6 @@ SetupResetReminder ( ) { EFI_INPUT_KEY Key; - CHAR16 *StringBuffer1; - CHAR16 *StringBuffer2; EFI_STATUS Status; EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2; @@ -4881,22 +4879,18 @@ SetupResetReminder ( // check any reset required change is applied? if yes, reset system // if (!EFI_ERROR (Status) && FormBrowserEx2->IsResetRequired ()) { - StringBuffer1 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16)); - ASSERT (StringBuffer1 != NULL); - StringBuffer2 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16)); - ASSERT (StringBuffer2 != NULL); - StrCpyS (StringBuffer1, MAX_CHAR, L"Configuration changed. Reset to apply it Now."); - StrCpyS (StringBuffer2, MAX_CHAR, L"Press ENTER to reset"); // // Popup a menu to notice user // do { - CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Configuration changed. Reset to apply it Now.", + L"Press ENTER to reset", + NULL); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - FreePool (StringBuffer1); - FreePool (StringBuffer2); - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } }