]> code.delx.au - refind/blobdiff - refind/main.c
Tweaks for OS X 10.10 (Yosemite) and new support to enable and lock
[refind] / refind / main.c
index f709e598bb767734e2634e8dcf862d432cd6eff3..e83940bcea6c1a281f6f4426a393b6e2cc0984a9 100644 (file)
@@ -139,8 +139,8 @@ 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, 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,
+REFIT_CONFIG GlobalConfig = { FALSE, TRUE, 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,
                                 TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, 0, 0, 0, 0, 0, 0 }
@@ -169,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.3");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.3.2");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2014 Roderick W. Smith");
@@ -267,7 +267,8 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths,
                                     IN CHAR16 *LoadOptions, IN UINTN LoaderType,
                                     IN CHAR16 *ImageTitle, IN CHAR8 OSType,
                                     OUT UINTN *ErrorInStep,
-                                    IN BOOLEAN Verbose)
+                                    IN BOOLEAN Verbose,
+                                    IN BOOLEAN IsDriver)
 {
     EFI_STATUS              Status, ReturnStatus;
     EFI_HANDLE              ChildImageHandle;
@@ -366,7 +367,8 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths,
 
 bailout_unload:
     // unload the image, we don't care if it works or not...
-    Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle);
+    if (!IsDriver)
+       Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle);
 
 bailout:
     MyFreePool(FullLoadOptions);
@@ -377,13 +379,15 @@ static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath,
                                 IN CHAR16 *LoadOptions, IN UINTN LoaderType,
                                 IN CHAR16 *ImageTitle, IN CHAR8 OSType,
                                 OUT UINTN *ErrorInStep,
-                                IN BOOLEAN Verbose)
+                                IN BOOLEAN Verbose,
+                                IN BOOLEAN IsDriver
+                               )
 {
     EFI_DEVICE_PATH *DevicePaths[2];
 
     DevicePaths[0] = DevicePath;
     DevicePaths[1] = NULL;
-    return StartEFIImageList(DevicePaths, LoadOptions, LoaderType, ImageTitle, OSType, ErrorInStep, Verbose);
+    return StartEFIImageList(DevicePaths, LoadOptions, LoaderType, ImageTitle, OSType, ErrorInStep, Verbose, IsDriver);
 } /* static EFI_STATUS StartEFIImage() */
 
 // From gummiboot: Reboot the computer into its built-in user interface
@@ -410,7 +414,8 @@ static EFI_STATUS RebootIntoFirmware(VOID) {
    return err;
 }
 
-// Record the value of the loader's name/description in rEFInd's "PreviousBoot" EFI variable.
+// 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;
@@ -423,20 +428,43 @@ static VOID StoreLoaderName(IN CHAR16 *Name) {
       } // if
       MyFreePool(OldName);
    } // if
-} // VOID StorePreviousLoader()
+} // VOID StoreLoaderName()
 
 //
 // EFI OS loader functions
 //
 
-static VOID StartLoader(LOADER_ENTRY *Entry)
+// See http://www.thomas-krenn.com/en/wiki/Activating_the_Intel_VT_Virtualization_Feature
+// for information on Intel VMX features
+static VOID DoEnableAndLockVMX(VOID)
+{
+    UINT32 msr = 0x3a;
+    UINT32 low_bits = 0, high_bits = 0;
+
+    // is VMX active ?
+    __asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr));
+
+    // enable and lock vmx if not locked
+    if ((low_bits & 1) == 0) {
+        high_bits = 0;
+        low_bits = 0x05;
+        msr = 0x3a;
+        __asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
+    } 
+} // VOID DoEnableAndLockVMX
+
+static VOID StartLoader(LOADER_ENTRY *Entry, CHAR16 *SelectionName)
 {
     UINTN ErrorInStep = 0;
 
+    if (GlobalConfig.EnableAndLockVMX) {
+        DoEnableAndLockVMX();
+    }
+
     BeginExternalScreen(Entry->UseGraphicsMode, L"Booting OS");
-    StoreLoaderName(Entry->me.Title);
+    StoreLoaderName(SelectionName);
     StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI,
-                  Basename(Entry->LoaderPath), Entry->OSType, &ErrorInStep, !Entry->UseGraphicsMode);
+                  Basename(Entry->LoaderPath), Entry->OSType, &ErrorInStep, !Entry->UseGraphicsMode, FALSE);
     FinishExternalScreen();
 }
 
@@ -1605,7 +1633,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;
@@ -1627,8 +1655,8 @@ 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);
+    StoreLoaderName(SelectionName);
+    Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, TYPE_LEGACY, L"legacy loader", 0, &ErrorInStep, TRUE, FALSE);
     if (Status == EFI_NOT_FOUND) {
         if (ErrorInStep == 1) {
             Print(L"\nPlease make sure that you have the latest firmware update installed.\n");
@@ -1641,10 +1669,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(Entry->me.Title);
+    StoreLoaderName(SelectionName);
 
     BdsLibConnectDevicePath (Entry->BdsOption->DevicePath);
     BdsLibDoLegacyBoot(Entry->BdsOption);
@@ -1973,7 +2001,7 @@ 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);
+                 Basename(Entry->LoaderPath), Entry->OSType, NULL, TRUE, FALSE);
    FinishExternalScreen();
 } /* static VOID StartTool() */
 
@@ -2021,7 +2049,7 @@ static UINTN ScanDriverDir(IN CHAR16 *Path)
         SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName);
         NumFound++;
         Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName),
-                               L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE);
+                               L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE, TRUE);
     }
     Status = DirIterClose(&DirIter);
     if (Status != EFI_NOT_FOUND) {
@@ -2508,7 +2536,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
@@ -2553,10 +2581,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) {
@@ -2584,15 +2612,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
@@ -2613,8 +2641,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