From de33b3554d3dde875eea6e1f1b3da54e22e2c326 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Sun, 28 Apr 2013 13:58:53 -0400 Subject: [PATCH] New "Reboot to Firmware User Interface" feature. --- CREDITS.txt | 8 ++-- NEWS.txt | 7 +++ docs/refind/configfile.html | 4 +- include/tiano_includes.h | 1 + refind.conf-sample | 6 ++- refind/config.c | 2 + refind/global.h | 3 +- refind/icns.c | 1 + refind/icns.h | 27 +++++------ refind/main.c | 90 +++++++++++++++++++++++++++++++++++-- 10 files changed, 125 insertions(+), 24 deletions(-) diff --git a/CREDITS.txt b/CREDITS.txt index b21792e..0ed0b47 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -24,7 +24,7 @@ Program (C source code) files: VirtualBox (https://www.virtualbox.org) and the Clover boot loader project (https://sourceforge.net/projects/cloverefiboot/). The filesystem-specific code comes from various sources, including Apple, - the Linux kernel, and Christoph Phisterer. + the Linux kernel, and Christoph Pfisterer. * Assorted support code is borrowed from the TianoCore EDK2 (https://sourceforge.net/projects/tianocore/), which is the reference @@ -37,7 +37,8 @@ Program (C source code) files: OSes on UEFI-based PCs. * The code for editing boot options (cursor_left(), cursor_right(), and - line_edit() in screen.c) is taken from gummiboot. + line_edit() in screen.c) is taken from gummiboot + (http://freedesktop.org/wiki/Software/gummiboot). * Stefan Agner (stefan@agner.ch) turned the original ext2fs/ext3fs driver into one that can read ext4fs. @@ -55,7 +56,8 @@ Program (C source code) files: * The PNG support, in the files libeg/lodepng.c and libeg/lodepng.h, is a slightly modified version of LodePNG (http://lodev.org/lodepng/) by Lode - Vandevenne. + Vandevenne. (The libeg/lodepng_xtra.c file provides some necessary + ancillary and interface functions written by me.) Icons and graphics: ------------------- diff --git a/NEWS.txt b/NEWS.txt index ea04e3f..46ce92f 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,6 +1,13 @@ 0.6.10 (?/??/2013): ------------------- +- Added new option to reboot the computer into the firmware's user + interface. This option is active by default, or can be set via the + "firmware" option to the "showtools" token in refind.conf. It works + on only some computers, though; older computers lack this feature, and + when rEFInd is told to use this feature on such computers, the directive + is quietly ignored. + - Upgraded LodePNG library from version 20121216 to 20130415 and restructured rEFInd-specific modifications to simplify future upgrades. diff --git a/docs/refind/configfile.html b/docs/refind/configfile.html index 85ceea9..73c0ca7 100644 --- a/docs/refind/configfile.html +++ b/docs/refind/configfile.html @@ -238,8 +238,8 @@ timeout 20 showtools - shell, gptsync, apple_recovery, mok_tool, about, exit, shutdown, and reboot - Specifies which tool tags to display on the second row. shell launches an EFI shell, gptsync launches a tool that creates a hybrid MBR, apple_recovery boots the OS X Recovery HD, mok_tool launches a tool to manage Machine Owner Keys (MOKs) on systems with Secure Boot active, about displays information about the program, exit terminates rEFInd, shutdown shuts down the computer (or reboots it, on some UEFI PCs), and reboot reboots the computer. The tags appear in the order in which you specify them. The default is shell, apple_recovery, mok_tool, about, shutdown, reboot. Note that the shell, apple_recovery, and mok_tool options all require the presence of programs not included with rEFInd. The gptsync option requires use of a like-named program which, although it ships with rEFInd 0.6.9 and later, is not installed by default except under OS X. See the "Installing Additional Components" section of the Installing rEFInd page for pointers to the shell and gptsync programs. The apple_recovery option will appear only if you've got an Apple Recovery HD partition (which has a boot loader called com.apple.recovery.boot/boot.efi). See the Secure Boot page for information on Secure Boot and MOK management. + shell, gptsync, apple_recovery, mok_tool, about, exit, shutdown, reboot, and firmware + Specifies which tool tags to display on the second row. shell launches an EFI shell, gptsync launches a tool that creates a hybrid MBR, apple_recovery boots the OS X Recovery HD, mok_tool launches a tool to manage Machine Owner Keys (MOKs) on systems with Secure Boot active, about displays information about the program, exit terminates rEFInd, shutdown shuts down the computer (or reboots it, on some UEFI PCs), reboot reboots the computer, and firmware reboots the computer into the firmware's own user interface. The tags appear in the order in which you specify them. The default is shell, apple_recovery, mok_tool, about, shutdown, reboot, firmware. Note that the shell, apple_recovery, and mok_tool options all require the presence of programs not included with rEFInd. The gptsync option requires use of a like-named program which, although it ships with rEFInd 0.6.9 and later, is not installed by default except under OS X. See the "Installing Additional Components" section of the Installing rEFInd page for pointers to the shell and gptsync programs. The apple_recovery option will appear only if you've got an Apple Recovery HD partition (which has a boot loader called com.apple.recovery.boot/boot.efi). The firmware option works only on computers that support this option; on other computers, the option is quietly ignored. See the Secure Boot page for information on Secure Boot and MOK management. font diff --git a/include/tiano_includes.h b/include/tiano_includes.h index 07eb2b1..9611243 100644 --- a/include/tiano_includes.h +++ b/include/tiano_includes.h @@ -14,6 +14,7 @@ #define Atoi StrDecimalToUintn #define SPrint UnicodeSPrint #define StrDuplicate EfiStrDuplicate +#define EFI_MAXIMUM_VARIABLE_SIZE 1024 #include #include diff --git a/refind.conf-sample b/refind.conf-sample index a9c28df..8a8b3f9 100644 --- a/refind.conf-sample +++ b/refind.conf-sample @@ -137,9 +137,11 @@ timeout 20 # shutdown - shuts down the computer (a bug causes this to reboot # EFI systems) # reboot - a tag to reboot the computer -# Default is shell,apple_recovery,mok_tool,about,shutdown,reboot +# firmware - a tag to reboot the computer into the firmware's +# user interface (ignored on older computers) +# Default is shell,apple_recovery,mok_tool,about,shutdown,reboot,firmware # -#showtools shell, mok_tool, about, reboot, exit +#showtools shell, mok_tool, about, reboot, exit, firmware # Directories in which to search for EFI drivers. These drivers can # provide filesystem support, give access to hard disks on plug-in diff --git a/refind/config.c b/refind/config.c index 871b0e6..36f0464 100644 --- a/refind/config.c +++ b/refind/config.c @@ -463,6 +463,8 @@ VOID ReadConfig(CHAR16 *FileName) GlobalConfig.ShowTools[i - 1] = TAG_APPLE_RECOVERY; } else if (StriCmp(FlagName, L"mok_tool") == 0) { GlobalConfig.ShowTools[i - 1] = TAG_MOK_TOOL; + } else if (StriCmp(FlagName, L"firmware") == 0) { + GlobalConfig.ShowTools[i - 1] = TAG_FIRMWARE; } else { Print(L" unknown showtools flag: '%s'\n", FlagName); } diff --git a/refind/global.h b/refind/global.h index 0aad5f1..a4d8355 100644 --- a/refind/global.h +++ b/refind/global.h @@ -70,7 +70,8 @@ #define TAG_LEGACY_UEFI (10) #define TAG_APPLE_RECOVERY (11) #define TAG_MOK_TOOL (12) -#define NUM_TOOLS (11) +#define TAG_FIRMWARE (13) +#define NUM_TOOLS (13) #define NUM_SCAN_OPTIONS 10 diff --git a/refind/icns.c b/refind/icns.c index f11ab1b..4a6b4d1 100644 --- a/refind/icns.c +++ b/refind/icns.c @@ -55,6 +55,7 @@ BUILTIN_ICON BuiltinIconTable[BUILTIN_ICON_COUNT] = { { NULL, L"func_reset", 48 }, { NULL, L"func_shutdown", 48 }, { NULL, L"func_exit", 48 }, + { NULL, L"func_firmware", 48 }, { NULL, L"tool_shell", 48 }, { NULL, L"tool_part", 48 }, { NULL, L"tool_rescue", 48 }, diff --git a/refind/icns.h b/refind/icns.h index c389abc..f709b42 100644 --- a/refind/icns.h +++ b/refind/icns.h @@ -55,19 +55,20 @@ EG_IMAGE * DummyImage(IN UINTN PixelSize); EG_IMAGE * BuiltinIcon(IN UINTN Id); -#define BUILTIN_ICON_FUNC_ABOUT (0) -#define BUILTIN_ICON_FUNC_RESET (1) -#define BUILTIN_ICON_FUNC_SHUTDOWN (2) -#define BUILTIN_ICON_FUNC_EXIT (3) -#define BUILTIN_ICON_TOOL_SHELL (4) -#define BUILTIN_ICON_TOOL_PART (5) -#define BUILTIN_ICON_TOOL_RESCUE (6) -#define BUILTIN_ICON_TOOL_APPLE_RESCUE (7) -#define BUILTIN_ICON_TOOL_MOK_TOOL (8) -#define BUILTIN_ICON_VOL_INTERNAL (9) -#define BUILTIN_ICON_VOL_EXTERNAL (10) -#define BUILTIN_ICON_VOL_OPTICAL (11) -#define BUILTIN_ICON_COUNT (12) +#define BUILTIN_ICON_FUNC_ABOUT (0) +#define BUILTIN_ICON_FUNC_RESET (1) +#define BUILTIN_ICON_FUNC_SHUTDOWN (2) +#define BUILTIN_ICON_FUNC_EXIT (3) +#define BUILTIN_ICON_FUNC_FIRMWARE (4) +#define BUILTIN_ICON_TOOL_SHELL (5) +#define BUILTIN_ICON_TOOL_PART (6) +#define BUILTIN_ICON_TOOL_RESCUE (7) +#define BUILTIN_ICON_TOOL_APPLE_RESCUE (8) +#define BUILTIN_ICON_TOOL_MOK_TOOL (9) +#define BUILTIN_ICON_VOL_INTERNAL (10) +#define BUILTIN_ICON_VOL_EXTERNAL (11) +#define BUILTIN_ICON_VOL_OPTICAL (12) +#define BUILTIN_ICON_COUNT (13) #endif diff --git a/refind/main.c b/refind/main.c index cca2d18..8679fd6 100644 --- a/refind/main.c +++ b/refind/main.c @@ -61,6 +61,10 @@ #include "../EfiLib/BdsHelper.h" #endif // __MAKEWITH_GNUEFI +#ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL +#endif + // // variables @@ -105,8 +109,9 @@ static REFIT_MENU_ENTRY MenuEntryAbout = { L"About rEFInd", TAG_ABOUT, 1, 0, 'A', NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryReset = { L"Reboot Computer", TAG_REBOOT, 1, 0, 'R', NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryShutdown = { L"Shut Down Computer", TAG_SHUTDOWN, 1, 0, 'U', NULL, NULL, NULL }; -static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 0, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryExit = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryFirmware = { L"Reboot to Firmware User Interface", TAG_FIRMWARE, 1, 0, 0, NULL, NULL, NULL }; static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot", L"Use arrow keys to move cursor; Enter to boot;", @@ -115,7 +120,11 @@ static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - {TAG_SHELL, TAG_APPLE_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }}; + { TAG_SHELL, TAG_APPLE_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, + 0, 0, 0, 0, 0, 0 } + }; + +const EFI_GUID GlobalGuid = EFI_GLOBAL_VARIABLE; // Structure used to hold boot loader filenames and time stamps in // a linked list; used to sort entries within a directory. @@ -135,7 +144,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.9.1"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.9.2"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2013 Roderick W. Smith"); @@ -311,6 +320,65 @@ static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, return StartEFIImageList(DevicePaths, LoadOptions, LoadOptionsPrefix, ImageTitle, OSType, ErrorInStep, Verbose); } /* static EFI_STATUS StartEFIImage() */ +// From gummiboot: Retrieve a raw EFI variable. +// Returns EFI status +static EFI_STATUS EfivarGetRaw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size) { + CHAR8 *buf; + UINTN l; + EFI_STATUS err; + + l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE; + buf = AllocatePool(l); + if (!buf) + return EFI_OUT_OF_RESOURCES; + + err = uefi_call_wrapper(RT->GetVariable, 5, name, vendor, NULL, &l, buf); + if (EFI_ERROR(err) == EFI_SUCCESS) { + *buffer = buf; + if (size) + *size = l; + } else + MyFreePool(buf); + return err; +} // EFI_STATUS EfivarGetRaw() + +// From gummiboot: Set an EFI variable +static EFI_STATUS EfivarSetRaw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent) { + UINT32 flags; + + flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS; + if (persistent) + flags |= EFI_VARIABLE_NON_VOLATILE; + + return uefi_call_wrapper(RT->SetVariable, 5, name, vendor, flags, size, buf); +} // EFI_STATUS EfivarSetRaw() + +// From gummiboot: Reboot the computer into its built-in user interface +static EFI_STATUS RebootIntoFirmware(VOID) { + CHAR8 *b; + UINTN size; + UINT64 osind; + EFI_STATUS err; + + osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + + err = EfivarGetRaw(&GlobalGuid, L"OsIndications", &b, &size); + if (err == EFI_SUCCESS) + osind |= (UINT64)*b; + MyFreePool(b); + + err = EfivarSetRaw(&GlobalGuid, L"OsIndications", (CHAR8 *)&osind, sizeof(UINT64), TRUE); + if (err != EFI_SUCCESS) + return err; + + uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL); + Print(L"Error calling ResetSystem: %r", err); + PauseForKey(); +// uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; +} + + // // EFI OS loader functions // @@ -1975,6 +2043,8 @@ static VOID ScanForTools(VOID) { CHAR16 *FileName = NULL, *MokLocations, *MokName, *PathName, Description[256]; REFIT_MENU_ENTRY *TempMenuEntry; UINTN i, j, k, VolumeIndex; + UINT64 osind; + CHAR8 *b = 0; MokLocations = StrDuplicate(MOK_LOCATIONS); if (MokLocations != NULL) @@ -2003,6 +2073,16 @@ static VOID ScanForTools(VOID) { TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_EXIT); AddMenuEntry(&MainMenu, TempMenuEntry); break; + case TAG_FIRMWARE: + if (EfivarGetRaw(&GlobalGuid, L"OsIndicationsSupported", &b, &j) == EFI_SUCCESS) { + osind = (UINT64)*b; + if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) { + TempMenuEntry = CopyMenuEntry(&MenuEntryFirmware); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_FIRMWARE); + AddMenuEntry(&MainMenu, TempMenuEntry); + } // if + } // if + break; case TAG_SHELL: j = 0; while ((FileName = FindCommaDelimited(SHELL_NAMES, j++)) != NULL) { @@ -2244,6 +2324,10 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) } break; + case TAG_FIRMWARE: // Reboot into firmware's user interface + RebootIntoFirmware(); + break; + } // switch() MyFreePool(Selection); Selection = (ChosenEntry->Title) ? StrDuplicate(ChosenEntry->Title) : NULL; -- 2.39.2