default_selection is NOT set.
0.8.2 (5/??/2014):
------------------
+- Changed behavior when default_selection is not set: It now boots the
+ previously-booted loader, assuming it's still available; if not, rEFInd
+ boots the first loader (as it does now). Behavior is unchanged if
+ default_selection is set. Note that this behavior depends on the ability
+ of rEFInd to store an EFI variable in NVRAM. It therefore fails on
+ systems with flaky NVRAM storage. You can view the previously-booted
+ loader in the
+ /sys/firmware/efi/efivars/PreviousBoot-36d08fa7-cf0b-42f5-8f14-68df73ed3740
+ variable under Linux.
+
+- Added icon for Mageia Linux (os_mageia.png).
+
- Fixed bug that could misidentify a not-quite-GUID as a GUID in a
manual boot stanza's "volume" line.
MountOSXESP() {
# Identify the ESP. Note: This returns the FIRST ESP found;
# if the system has multiple disks, this could be wrong!
- Temp=`diskutil list | grep " EFI " | grep -o 'disk.*'`
+ Temp=$(mount | sed -n -E "/^(\/dev\/disk[0-9]+s[0-9]+) on \/ \(.*$/s//\1/p")
+ if [ $Temp ]; then
+ Temp=$(diskutil list $Temp | sed -n -E '/^ *[0-9]+:[ ]+EFI EFI[ ]+[0-9.]+ [A-Z]+[ ]+(disk[0-9]+s[0-9]+)$/ { s//\1/p
+ q
+ }' )
+ if [ -z $Temp ]; then
+ echo "Warning: root device doesn't have an EFI partition"
+ fi
+ else
+ echo "Warning: root device could not be found"
+ fi
+ if [ -z $Temp ]; then
+ Temp=$(diskutil list | sed -n -E '/^ *[0-9]+:[ ]+EFI EFI[ ]+[0-9.]+ [A-Z]+[ ]+(disk[0-9]+s[0-9]+)$/ { s//\1/p
+ q
+ }' )
+
+ if [ -z $Temp ]; then
+ echo "Could not find an EFI partition. Aborting!"
+ exit 1
+ fi
+ fi
Esp=/dev/`echo $Temp`
# If the ESP is mounted, use its current mount point....
Temp=`df -P | grep "$Esp"`
#include "global.h"
#include "mok.h"
#include "../include/refit_call_wrapper.h"
+#include "../refind/lib.h"
+#include "../refind/screen.h"
-static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, UINTN *size, VOID **buffer)
-{
- EFI_STATUS efi_status;
- char allocate = !(*size);
-
- efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, buffer);
-
- if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) {
- return efi_status;
- }
-
- *buffer = AllocatePool(*size);
-
- if (!*buffer) {
- Print(L"Unable to allocate variable buffer\n");
- return EFI_OUT_OF_RESOURCES;
- }
-
- efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, *buffer);
-
- return efi_status;
-} // get_variable()
/*
* Check whether we're in Secure Boot and user mode
EFI_STATUS status;
EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
UINTN charsize = sizeof(char);
- UINT8 sb, setupmode;
- UINT32 attributes;
-
- status = get_variable(L"SecureBoot", global_var, &attributes, &charsize, (VOID *)&sb);
+ UINT8 *sb = NULL, *setupmode = NULL;
+ status = EfivarGetRaw(&global_var, L"SecureBoot", (CHAR8 **) &sb, &charsize);
/* FIXME - more paranoia here? */
- if (status != EFI_SUCCESS || sb != 1) {
+ if (status != EFI_SUCCESS || charsize != sizeof(CHAR8) || *sb != 1) {
return FALSE;
}
- status = get_variable(L"SetupMode", global_var, &attributes, &charsize, (VOID *)&setupmode);
-
- if (status == EFI_SUCCESS && setupmode == 1) {
+ status = EfivarGetRaw(&global_var, L"SetupMode", (CHAR8 **) &setupmode, &charsize);
+ if (status == EFI_SUCCESS && charsize == sizeof(CHAR8) && *setupmode == 1) {
return FALSE;
}
} SHIM_LOCK;
#endif
+//EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, UINTN *size, VOID **buffer);
BOOLEAN ShimLoaded(void);
BOOLEAN ShimValidate (VOID *data, UINT32 size);
BOOLEAN secure_mode (VOID);
#include "config.h"
#include "screen.h"
#include "../include/refit_call_wrapper.h"
+#include "../mok/mok.h"
// constants
CHAR16 *FlagName;
CHAR16 *TempStr = NULL;
UINTN TokenCount, i;
+ EFI_GUID RefindGuid = REFIND_GUID_VALUE;
// Set a few defaults only if we're loading the default file.
if (StriCmp(FileName, GlobalConfig.ConfigFilename) == 0) {
MyFreePool(GlobalConfig.DontScanVolumes);
GlobalConfig.DontScanVolumes = StrDuplicate(DONT_SCAN_VOLUMES);
GlobalConfig.WindowsRecoveryFiles = StrDuplicate(WINDOWS_RECOVERY_FILES);
+ if (GlobalConfig.DefaultSelection != NULL) {
+ MyFreePool(GlobalConfig.DefaultSelection);
+ GlobalConfig.DefaultSelection = NULL;
+ }
+// GlobalConfig.DefaultSelection = AllocatePool(255 * sizeof(CHAR16));
+// Print(L"About to call EfivarGetRaw()\n");
+ Status = EfivarGetRaw(&RefindGuid, L"PreviousBoot", (CHAR8**) &(GlobalConfig.DefaultSelection), &i);
+// i = 255 * sizeof(CHAR16);
+// Print(L"About to call RT->GetVariable()\n");
+// Status = refit_call5_wrapper(RT->GetVariable, L"PreviousBoot", &RefindGuid, &Attributes, &i, GlobalConfig.DefaultSelection);
+ if (Status != EFI_SUCCESS)
+ GlobalConfig.DefaultSelection = NULL;
} // if
if (!FileExists(SelfDir, FileName)) {
// Files that may be Windows recovery files
#define WINDOWS_RECOVERY_FILES L"EFI\\Microsoft\\Boot\\LrsBootmgr.efi"
-#define NULL_GUID_VALUE { 00000000, 0000, 0000, {0000, 0000, 0000, 0000} };
+#define NULL_GUID_VALUE { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
+#define REFIND_GUID_VALUE { 0x36D08FA7, 0xCF0B, 0x42F5, {0x8F, 0x14, 0x68, 0xDF, 0x73, 0xED, 0x37, 0x40} };
//
// global definitions
return EFI_SUCCESS;
}
+//
+// EFI variable read and write functions
+//
+
+// From gummiboot: Retrieve a raw EFI variable.
+// Returns EFI status
+EFI_STATUS EfivarGetRaw(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 = refit_call5_wrapper(RT->GetVariable, 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
+EFI_STATUS EfivarSetRaw(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 refit_call5_wrapper(RT->SetVariable, name, vendor, flags, size, buf);
+} // EFI_STATUS EfivarSetRaw()
+
//
// list functions
//
VOID UninitRefitLib(VOID);
EFI_STATUS ReinitRefitLib(VOID);
+EFI_STATUS EfivarGetRaw(EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size);
+EFI_STATUS EfivarSetRaw(EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent);
+
VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName);
VOID CreateList(OUT VOID ***ListPtr, OUT UINTN *ElementCount, IN UINTN InitialElementCount);
VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID *NewElement);
};
EFI_GUID GlobalGuid = EFI_GLOBAL_VARIABLE;
+EFI_GUID RefindGuid = REFIND_GUID_VALUE;
GPT_DATA *gPartitions = NULL;
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.1.2");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.1.3");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2014 Roderick W. Smith");
return StartEFIImageList(DevicePaths, LoadOptions, LoaderType, ImageTitle, OSType, ErrorInStep, Verbose);
} /* static EFI_STATUS StartEFIImage() */
-// From gummiboot: Retrieve a raw EFI variable.
-// Returns EFI status
-static EFI_STATUS EfivarGetRaw(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 = refit_call5_wrapper(RT->GetVariable, 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(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 refit_call5_wrapper(RT->SetVariable, 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;
return err;
}
+// Record the value of the loader's name/description in rEFInd's "PreviousBoot" EFI variable.
+static VOID StoreLoaderName(IN CHAR16 *Name) {
+ EFI_STATUS Status;
+ CHAR16 *OldName = NULL;
+ UINTN Length;
+
+ if (Name) {
+ Status = EfivarGetRaw(&RefindGuid, L"PreviousBoot", (CHAR8**) &OldName, &Length);
+ if ((Status != EFI_SUCCESS) || (StrCmp(OldName, Name) != 0)) {
+ EfivarSetRaw(&RefindGuid, L"PreviousBoot", (CHAR8*) Name, StrLen(Name) * 2 + 2, TRUE);
+ } // if
+ MyFreePool(OldName);
+ } // if
+} // VOID StorePreviousLoader()
//
// EFI OS loader functions
UINTN ErrorInStep = 0;
BeginExternalScreen(Entry->UseGraphicsMode, L"Booting OS");
+ StoreLoaderName(Entry->me.Title);
StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI,
Basename(Entry->LoaderPath), Entry->OSType, &ErrorInStep, !Entry->UseGraphicsMode);
FinishExternalScreen();
if (Entry != NULL) {
Entry->Title = StrDuplicate((LoaderTitle != NULL) ? LoaderTitle : LoaderPath);
Entry->me.Title = AllocateZeroPool(sizeof(CHAR16) * 256);
+ // Extra space at end of Entry->me.Title enables searching on Volume->VolName even if another volume
+ // name is identical except for something added to the end (e.g., VolB1 vs. VolB12).
SPrint(Entry->me.Title, 255, L"Boot %s from %s ", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath, Volume->VolName);
Entry->me.Row = 0;
Entry->me.BadgeImage = Volume->VolBadgeImage;
ExtractLegacyLoaderPaths(DiscoveredPathList, MAX_DISCOVERED_PATHS, LegacyLoaderList);
+ StoreLoaderName(Entry->me.Title);
Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, TYPE_LEGACY, L"legacy loader", 0, &ErrorInStep, TRUE);
if (Status == EFI_NOT_FOUND) {
if (ErrorInStep == 1) {
static VOID StartLegacyUEFI(LEGACY_ENTRY *Entry)
{
BeginExternalScreen(TRUE, L"Booting Legacy OS (UEFI mode)");
+ StoreLoaderName(Entry->me.Title);
BdsLibConnectDevicePath (Entry->BdsOption->DevicePath);
BdsLibDoLegacyBoot(Entry->BdsOption);
static VOID StartTool(IN LOADER_ENTRY *Entry)
{
BeginExternalScreen(Entry->UseGraphicsMode, Entry->me.Title + 6); // assumes "Start <title>" as assigned below
+ StoreLoaderName(Entry->me.Title);
StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI,
Basename(Entry->LoaderPath), Entry->OSType, NULL, TRUE);
FinishExternalScreen();