]> code.delx.au - refind/commitdiff
Added ability to boot the previously-booted loader if
authorsrs5694 <srs5694@users.sourceforge.net>
Sun, 8 Jun 2014 01:05:30 +0000 (21:05 -0400)
committersrs5694 <srs5694@users.sourceforge.net>
Sun, 8 Jun 2014 01:05:30 +0000 (21:05 -0400)
default_selection is NOT set.

NEWS.txt
install.sh
mok/mok.c
mok/mok.h
refind/config.c
refind/global.h
refind/lib.c
refind/lib.h
refind/main.c

index fac4224a818ff3aca5ea07fca9462695c0df6d95..1e5686dbc435af11267deaf7e550c1da0e8e6981 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,6 +1,18 @@
 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.
 
index cb876063a1fe4ff7217e770e7d02c5afa1664a9f..67df9ee3e5c851ec6bfab490214ddcee0d73db1a 100755 (executable)
@@ -446,7 +446,27 @@ MountDefaultTarget() {
 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"`
index 3948b08af03d6482f70b6855c4a86ff5a5a56fe5..6b47522f90ae0dae5378a32773d30452798253ce 100644 (file)
--- a/mok/mok.c
+++ b/mok/mok.c
 #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
@@ -79,19 +59,16 @@ BOOLEAN secure_mode (VOID)
    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;
    }
 
index 7648209d5c2ec787a4a1b6b381381f870df9b31c..d24e2b4a4b62d134fbf9696116334dd680151d70 100644 (file)
--- a/mok/mok.h
+++ b/mok/mok.h
@@ -24,6 +24,7 @@ typedef struct _SHIM_LOCK
 } 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);
index 09018159a8184bbfb4523c1406923d853ca41e30..e261ef8b4c91d677d9e834400b77d787d02ae98e 100644 (file)
@@ -50,6 +50,7 @@
 #include "config.h"
 #include "screen.h"
 #include "../include/refit_call_wrapper.h"
+#include "../mok/mok.h"
 
 // constants
 
@@ -430,6 +431,7 @@ VOID ReadConfig(CHAR16 *FileName)
     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) {
@@ -454,6 +456,18 @@ VOID ReadConfig(CHAR16 *FileName)
        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)) {
index e7aee6255f9f02d4b740230f12582eb84f255a91..3b22f1d2d612a07b72ac0d1f0cfdf1e63ba590b4 100644 (file)
 // 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
index 12b5ce389f2dc1f6bcfd7592aba47e1032a9c2fc..057026589c502b104180d336c3a8cb2771b85b81 100644 (file)
@@ -265,6 +265,43 @@ static EFI_STATUS FinishInitRefitLib(VOID)
     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
 //
index 15754cd676b3ea4133f2143454d11789d4b7c2de..e6a8c3026ef330a5318a675f31a27a912e33a329 100644 (file)
@@ -85,6 +85,9 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle);
 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);
index da6026d860ea93f3b68e9b5bf52834074852678e..f709e598bb767734e2634e8dcf862d432cd6eff3 100644 (file)
@@ -147,6 +147,7 @@ REFIT_CONFIG GlobalConfig = { FALSE, FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MOD
                             };
 
 EFI_GUID GlobalGuid = EFI_GLOBAL_VARIABLE;
+EFI_GUID RefindGuid = REFIND_GUID_VALUE;
 
 GPT_DATA *gPartitions = NULL;
 
@@ -168,7 +169,7 @@ static VOID AboutrEFInd(VOID)
 
     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");
@@ -385,39 +386,6 @@ static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath,
     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;
@@ -442,6 +410,20 @@ static EFI_STATUS RebootIntoFirmware(VOID) {
    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
@@ -452,6 +434,7 @@ static VOID StartLoader(LOADER_ENTRY *Entry)
     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();
@@ -1016,6 +999,8 @@ LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN
    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;
@@ -1642,6 +1627,7 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry)
 
     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) {
@@ -1658,6 +1644,7 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry)
 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);
@@ -1984,6 +1971,7 @@ static VOID ScanLegacyExternal(VOID)
 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();