Index: stand/efi/include/efiapi.h =================================================================== --- stand/efi/include/efiapi.h +++ stand/efi/include/efiapi.h @@ -229,6 +229,15 @@ // Variable size limitation #define EFI_MAXIMUM_VARIABLE_SIZE 1024 +// OsIndications +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 +#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002 +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED 0x0000000000000004 +#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED 0x0000000000000008 +#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED 0x0000000000000010 +#define EFI_OS_INDICATIONS_START_OS_RECOVERY 0x0000000000000020 +#define EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY 0x0000000000000040 + typedef EFI_STATUS (EFIAPI *EFI_GET_VARIABLE) ( Index: stand/efi/include/efilib.h =================================================================== --- stand/efi/include/efilib.h +++ stand/efi/include/efilib.h @@ -137,6 +137,7 @@ EFI_STATUS efi_freebsd_getenv(const char *v, void *data, __size_t *len); EFI_STATUS efi_getenv(EFI_GUID *g, const char *v, void *data, __size_t *len); EFI_STATUS efi_global_getenv(const char *v, void *data, __size_t *len); +EFI_STATUS efi_global_setenv(const char *v, UINT32 attr, void *data, __size_t len); EFI_STATUS efi_setenv(EFI_GUID *guid, const char *varname, UINT32 attr, void *data, __size_t len); EFI_STATUS efi_setenv_freebsd_wcs(const char *varname, CHAR16 *valstr); Index: stand/efi/libefi/efienv.c =================================================================== --- stand/efi/libefi/efienv.c +++ stand/efi/libefi/efienv.c @@ -61,6 +61,13 @@ return (efi_getenv(&GlobalBootVarGUID, v, data, len)); } +EFI_STATUS +efi_global_setenv(const char *v, UINT32 attr, void *data, size_t len) +{ + + return (efi_setenv(&GlobalBootVarGUID, v, attr, data, len)); +} + EFI_STATUS efi_freebsd_getenv(const char *v, void *data, size_t *len) { Index: stand/efi/libefi/env.c =================================================================== --- stand/efi/libefi/env.c +++ stand/efi/libefi/env.c @@ -1001,3 +1001,86 @@ #endif return (CMD_OK); } + +static int +efi_osindications_supported(uint64_t *supported) +{ + uint64_t supported64; + uint32_t supported32; + size_t vsize; + EFI_STATUS status; + + /* Historical artifact: older firmware uses a uint32. */ + vsize = sizeof(supported32); + status = efi_global_getenv("OsIndicationsSupported", &supported32, + &vsize); + if (status == EFI_SUCCESS) { + *supported = status; + return (EFI_SUCCESS); + } else if (status != EFI_BUFFER_TOO_SMALL) { + return (status); + } + + vsize = sizeof(supported64); + status = efi_global_getenv("OsIndicationsSupported", &supported64, + &vsize); + if (status != EFI_SUCCESS) { + return (status); + } + + *supported = supported64; + return (EFI_SUCCESS); +} + +COMMAND_SET(efi_setup, "efi-setup", "enter EFI setup menu", command_efi_setup); + +static int +command_efi_setup(int argc, char *argv[]) +{ + uint64_t indications, supported; + size_t vsize; + EFI_STATUS status; + UINT32 attr; + + status = efi_osindications_supported(&supported); + if (status != EFI_SUCCESS) { + if (status != EFI_NOT_FOUND) { + printf("Failed to fetch supported indications\n"); + } else { + printf("Error fetching supported indications: %d\n", + status); + } + + return (CMD_ERROR); + } + + if ((supported & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) == 0) { + printf("Boot to firmware not supported on this system.\n"); + return (CMD_ERROR); + } + + indications = 0; + vsize = sizeof(indications); + status = efi_global_getenv("OsIndications", &indications, &vsize); + if (status != EFI_SUCCESS && status != EFI_NOT_FOUND) { + printf("Error fetching current indications: %d\n", + status); + return (CMD_ERROR); + } + + /* EFI_NOT_FOUND left it at 0. */ + indications |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + /* v2.6 table 11 */ + attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS; + status = efi_global_setenv("OsIndications", attr, &indications, + vsize); + if (status != EFI_SUCCESS) { + printf("Error setting boot to firmware: %d\n", status); + return (CMD_ERROR); + } + + /* Reboot */ + efi_reboot(); + return (CMD_ERROR); +}