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..d4df2a138f
--- /dev/null
+++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c
@@ -0,0 +1,778 @@
+/** @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[] = SV_BOOT_DATA_VAR;
+STATIC CHAR16 mVarStoreName[] = L"SvBootFormData";
+STATIC CHAR16 mSvBootConfigVarName[] = SV_BOOT_CONFIG_VAR;
+
+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;
+ EFI_FORM_ID FormId;
+
+ 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 not be verification failure
+ 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;
+ }
+
+ 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
+ //
+ 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);
+ }
+
+ 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
+ //
+ gBS->SetWatchdogTimer (0, 0, 0, NULL);
+
+ // Display the form
+ Status = FormBrowser2->SendForm (
+ FormBrowser2,
+ &HiiHandle,
+ 1,
+ &gSovereignBootWizardFormSetGuid,
+ FormId,
+ 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..4b69ea7046
--- /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 _SV_BOOT_WIZARD_H_
+#define _SV_BOOT_WIZARD_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..f5b82fd765
--- /dev/null
+++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h
@@ -0,0 +1,65 @@
+/** @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
+#include
+
+#define SOVEREIGN_BOOT_WIZARD_FORM_DATA_VARSTORE_ID 0x0001
+
+#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
+
+
+#pragma pack(1)
+
+// 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..e9c65e1f87
--- /dev/null
+++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr
@@ -0,0 +1,177 @@
+///** @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);
+ 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.
+ 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),
+ 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;
+
+ 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),
+ 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);
+
+ 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);
+ 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;
+
+ 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),
+ 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);
+ subtitle text = STRING_TOKEN(STR_LAUNCH_REASON);
+
+ 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..a1700eb372
--- /dev/null
+++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni
@@ -0,0 +1,76 @@
+// *++
+//
+// 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"
+
+
+// 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"
+#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 ""
+#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"
+ "* 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_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_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
+#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..512ce80fd8 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]
@@ -89,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..e84eaeae48
--- /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 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
+#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
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 {
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
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/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/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/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
index e4559413c7..016a0dad80 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"Sovereign 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..aa17cdebc3 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,75 @@ 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
+ );
+ }
+
+ 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) {
+ 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/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
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index ebc3f821e4..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
@@ -1078,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
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr
index 88622f503f..85517ac8c6 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr
@@ -70,6 +70,52 @@ 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;
+
+ // Hidden checkbox for provisioned state, to be used in callback
+ // when default settings 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);
+ //
+ // 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..e33df6842e 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
@@ -298,6 +299,105 @@ SaveSecureBootVariable (
return Status;
}
+/**
+ Set Sovereign Boot configuration into variable space.
+
+ @param[in] SvBootEnable The state 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;
+}
+
+/**
+ 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.
@@ -3461,9 +3561,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 +3637,27 @@ 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);
+ }
+
+ HiiSetString (
+ Private->HiiHandle,
+ STRING_TOKEN (STR_SOVEREIGN_BOOT_STATE_CONTENT),
+ ConfigData->SvBootProvisioned ? L"Yes" : L"No",
+ NULL);
+ }
+
if (SecureBootEnable != NULL) {
FreePool (SecureBootEnable);
}
@@ -3734,6 +3858,13 @@ SecureBootRouteConfig (
}
}
+ if (IfrNvData.SvBootAvailable) {
+ Status = SaveSovereignBootVariable (IfrNvData.SvBootEnable);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
*Progress = Configuration + StrLen (Configuration);
return EFI_SUCCESS;
}
@@ -4725,6 +4856,45 @@ 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;
+ 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 ()) {
+ //
+ // Popup a menu to notice user
+ //
+ do {
+ 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);
+
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+}
+
/**
This function is called to provide results data to the driver.
@@ -4914,6 +5084,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) &&
@@ -4949,6 +5134,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:
@@ -5444,6 +5657,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
//
@@ -5470,6 +5693,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
//
@@ -5478,6 +5712,38 @@ 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);
+ 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
+ //
+ Status = UpdateSecureBootString (Private);
+ if (GetBrowserDataResult) {
+ SecureBootExtractConfigFromVariable (Private, IfrNvData);
+ }
+ }
+
+ break;
+ }
+ case KEY_LAUNCH_SOVEREIGN_BOOT_WIZARD:
+ {
+ SetupResetReminder ();
+ Status = EfiBootManagerLaunchSovereignBootWizard (SV_BOOT_LAUNCH_VIA_SETUP);
+ break;
}
default:
break;
@@ -5508,6 +5774,25 @@ 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;
+ }
+ case KEY_SOVEREIGN_BOOT_PROVISIONED:
+ {
+ Status = EFI_SUCCESS;
+ Value->b = FALSE;
+ mResetSvBootState = TRUE;
+ 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..fe7fb2dea0 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h
@@ -75,6 +75,10 @@ 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 KEY_SOVEREIGN_BOOT_PROVISIONED 0x1122
+
#define LABEL_KEK_DELETE 0x1200
#define LABEL_DB_DELETE 0x1201
#define LABEL_SIGNATURE_LIST_START 0x1202
@@ -138,6 +142,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..43b4dc4a00 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,26 @@ 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 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."
+
+#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"