]> code.delx.au - refind/blobdiff - refind/main.c
Version 0.8.2 release; refinement to last-booted as default selection
[refind] / refind / main.c
index 5ef09c5bbe20c4fa4935b2e303c41fdef9b021a1..aacbe93b848a4c5975c273fe17881f7d269d893e 100644 (file)
@@ -139,7 +139,7 @@ static REFIT_MENU_SCREEN MainMenu       = { L"Main Menu", NULL, 0, NULL, 0, NULL
                                             L"Insert or F2 for more options; Esc to refresh" };
 static REFIT_MENU_SCREEN AboutMenu      = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL, L"Press Enter to return to main menu", L"" };
 
-REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, 0,
+REFIT_CONFIG GlobalConfig = { FALSE, FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, 0,
                               { DEFAULT_BIG_ICON_SIZE / 4, DEFAULT_SMALL_ICON_SIZE, DEFAULT_BIG_ICON_SIZE }, BANNER_NOSCALE,
                               NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                               { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY, TAG_MOK_TOOL,
@@ -147,6 +147,7 @@ REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20,
                             };
 
 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.0.7");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.2");
         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,16 +410,32 @@ static EFI_STATUS RebootIntoFirmware(VOID) {
    return err;
 }
 
+// Record the value of the loader's name/description in rEFInd's "PreviousBoot" EFI variable,
+// if it's different from what's already stored there.
+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 StoreLoaderName()
 
 //
 // EFI OS loader functions
 //
 
-static VOID StartLoader(LOADER_ENTRY *Entry)
+static VOID StartLoader(LOADER_ENTRY *Entry, CHAR16 *SelectionName)
 {
     UINTN ErrorInStep = 0;
 
     BeginExternalScreen(Entry->UseGraphicsMode, L"Booting OS");
+    StoreLoaderName(SelectionName);
     StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI,
                   Basename(Entry->LoaderPath), Entry->OSType, &ErrorInStep, !Entry->UseGraphicsMode);
     FinishExternalScreen();
@@ -1016,6 +1000,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;
@@ -1620,7 +1606,7 @@ static EFI_DEVICE_PATH *LegacyLoaderList[] = {
 
 #define MAX_DISCOVERED_PATHS (16)
 
-static VOID StartLegacy(IN LEGACY_ENTRY *Entry)
+static VOID StartLegacy(IN LEGACY_ENTRY *Entry, IN CHAR16 *SelectionName)
 {
     EFI_STATUS          Status;
     EG_IMAGE            *BootLogoImage;
@@ -1642,6 +1628,7 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry)
 
     ExtractLegacyLoaderPaths(DiscoveredPathList, MAX_DISCOVERED_PATHS, LegacyLoaderList);
 
+    StoreLoaderName(SelectionName);
     Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, TYPE_LEGACY, L"legacy loader", 0, &ErrorInStep, TRUE);
     if (Status == EFI_NOT_FOUND) {
         if (ErrorInStep == 1) {
@@ -1655,9 +1642,10 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry)
 } /* static VOID StartLegacy() */
 
 // Start a device on a non-Mac using the EFI_LEGACY_BIOS_PROTOCOL
-static VOID StartLegacyUEFI(LEGACY_ENTRY *Entry)
+static VOID StartLegacyUEFI(LEGACY_ENTRY *Entry, CHAR16 *SelectionName)
 {
     BeginExternalScreen(TRUE, L"Booting Legacy OS (UEFI mode)");
+    StoreLoaderName(SelectionName);
 
     BdsLibConnectDevicePath (Entry->BdsOption->DevicePath);
     BdsLibDoLegacyBoot(Entry->BdsOption);
@@ -1737,9 +1725,6 @@ static LEGACY_ENTRY * AddLegacyEntry(IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Vo
 } /* static LEGACY_ENTRY * AddLegacyEntry() */
 
 
-// #ifdef __MAKEWITH_GNUEFI
-// static VOID ScanLegacyUEFI(IN UINTN DiskType){}
-// #else
 // default volume badge icon based on disk kind
 static EG_IMAGE * GetDiskBadge(IN UINTN DiskType) {
    EG_IMAGE * Badge = NULL;
@@ -1891,7 +1876,6 @@ static VOID ScanLegacyUEFI(IN UINTN DiskType)
         Index++;
     } // while
 } /* static VOID ScanLegacyUEFI() */
-//#endif // __MAKEWITH_GNUEFI
 
 static VOID ScanLegacyVolume(REFIT_VOLUME *Volume, UINTN VolumeIndex) {
    UINTN VolumeIndex2;
@@ -1988,6 +1972,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();
@@ -2214,8 +2199,8 @@ static VOID ScanForBootloaders(VOID) {
          ScanForLegacy = TRUE;
    } // for
 
-   // If UEFI & scanning for legacy loaders, update NVRAM boot manager list
-   if ((GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) && ScanForLegacy) {
+   // If UEFI & scanning for legacy loaders & deep legacy scan, update NVRAM boot manager list
+   if ((GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) && ScanForLegacy && GlobalConfig.DeepLegacyScan) {
       BdsDeleteAllInvalidLegacyBootOptions();
       BdsAddNonExistingLegacyBootOptions();
    } // if
@@ -2524,7 +2509,7 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     BOOLEAN            MokProtocol;
     REFIT_MENU_ENTRY   *ChosenEntry;
     UINTN              MenuExit, i;
-    CHAR16             *Selection = NULL;
+    CHAR16             *SelectionName = NULL;
     EG_PIXEL           BGColor;
 
     // bootstrap
@@ -2569,10 +2554,10 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     } // if
 
     if (GlobalConfig.DefaultSelection)
-       Selection = StrDuplicate(GlobalConfig.DefaultSelection);
+       SelectionName = StrDuplicate(GlobalConfig.DefaultSelection);
 
     while (MainLoopRunning) {
-        MenuExit = RunMainMenu(&MainMenu, Selection, &ChosenEntry);
+        MenuExit = RunMainMenu(&MainMenu, &SelectionName, &ChosenEntry);
 
         // The Escape key triggers a re-scan operation....
         if (MenuExit == MENU_EXIT_ESCAPE) {
@@ -2600,15 +2585,15 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
                 break;
 
             case TAG_LOADER:   // Boot OS via .EFI loader
-                StartLoader((LOADER_ENTRY *)ChosenEntry);
+                StartLoader((LOADER_ENTRY *)ChosenEntry, SelectionName);
                 break;
 
             case TAG_LEGACY:   // Boot legacy OS
-                StartLegacy((LEGACY_ENTRY *)ChosenEntry);
+                StartLegacy((LEGACY_ENTRY *)ChosenEntry, SelectionName);
                 break;
 
             case TAG_LEGACY_UEFI: // Boot a legacy OS on a non-Mac
-                StartLegacyUEFI((LEGACY_ENTRY *)ChosenEntry);
+                StartLegacyUEFI((LEGACY_ENTRY *)ChosenEntry, SelectionName);
                 break;
 
             case TAG_TOOL:     // Start a EFI tool
@@ -2629,8 +2614,6 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
                 break;
 
         } // switch()
-        MyFreePool(Selection);
-        Selection = (ChosenEntry->Title) ? StrDuplicate(ChosenEntry->Title) : NULL;
     } // while()
 
     // If we end up here, things have gone wrong. Try to reboot, and if that