]> code.delx.au - refind/commitdiff
New support for legacy BIOS booting on PCs
authorsrs5694 <srs5694@users.sourceforge.net>
Sun, 30 Sep 2012 18:27:43 +0000 (14:27 -0400)
committersrs5694 <srs5694@users.sourceforge.net>
Sun, 30 Sep 2012 18:27:43 +0000 (14:27 -0400)
EfiLib/Make.tiano
Makefile
refind.conf-sample
refind.inf
refind/global.h
refind/main.c

index 2e2e5b3203c1781bd25d6e57fe4df28c2c23cc7b..66dd9ee95f990640ae25f5d9ab7290055a705c3a 100644 (file)
@@ -5,7 +5,7 @@
 
 include ../Make.tiano
 
-SOURCE_NAMES     = BdsConnect BmLib Console DevicePath 
+SOURCE_NAMES     = BdsConnect BmLib Console DevicePath BdsHelper BdsTianoCore
 OBJS             = $(SOURCE_NAMES:=.obj)
 #DRIVERNAME      = ext2
 #BUILDME          = $(DRIVERNAME)_$(FILENAME_CODE).efi
index 348592c398231fb0951ba5f0de658e6dc97658b9..5cbc948559869bfbdff121871e3a906df3913c18 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ LIBEG_DIR=libeg
 EFILIB_DIR=EfiLib
 
 # Build rEFInd, including libeg
-all:   gnuefi
+all:   tiano
 
 gnuefi:
        make -C $(LIBEG_DIR)
index 6431b781a80cac2317b9c1a2df8f9de9bc1a8dd4..09d29107cc7e0907a4b2794c39829d7a4c17e176 100644 (file)
@@ -118,10 +118,13 @@ timeout 20
 #  hdbios        - BIOS disk-based boot loaders
 #  biosexternal  - BIOS external boot loaders (USB, eSATA, etc.)
 #  cd            - BIOS optical-disc boot loaders
+#  legacypc      - BIOS target alternative search that may work on non-Mac 
+#                  machines. Use in place of the other BIOS options.
 #  manual        - use stanzas later in this configuration file
 # Default is internal,external,optical
 #
 #scanfor internal,external,optical
+scanfor internal,external,legacypc
 
 # When scanning volumes for EFI boot loaders, rEFInd always looks for
 # Mac OS X's and Microsoft Windows' boot loaders in their normal locations,
index f1bcef1e6f3af00701f72d5c80d9f6fb69bd5b4c..a478b0c564f4792af0aad145c356f58cff67cbcc 100644 (file)
@@ -30,6 +30,8 @@
   EfiLib/BmLib.c\r
   EfiLib/DevicePath.c #included into GenericBdsLib\r
   EfiLib/BdsConnect.c #included into GenericBdsLib\r
+  EfiLib/BdsHelper.c\r
+  EfiLib/BdsTianoCore.c\r
   EfiLib/Console.c\r
   refind/main.c\r
   refind/config.c\r
index 905f79adf1e2019079b6deacfaaba51c90476b0b..a42f61976b61ba87286f910e9059a06f49fe99b4 100644 (file)
@@ -50,6 +50,7 @@
 #include <efilib.h>
 #else
 #include "../include/tiano_includes.h"
+#include "../EfiLib/GenericBdsLib.h"
 #endif
 
 #include "libeg.h"
@@ -66,6 +67,7 @@
 #define TAG_EXIT     (7)
 #define TAG_SHELL    (8)
 #define TAG_GPTSYNC  (9)
+#define TAG_LEGACY_NON_MAC (10)
 #define NUM_TOOLS    (9)
 
 #define NUM_SCAN_OPTIONS 10
@@ -155,12 +157,25 @@ typedef struct {
    CHAR8            OSType;
 } LOADER_ENTRY;
 
+typedef struct {
+   REFIT_MENU_ENTRY  me;
+   REFIT_VOLUME      *Volume;
+#ifdef __MAKEWITH_TIANO
+   BDS_COMMON_OPTION *BdsOption;
+#endif // __MAKEWITH_TIANO
+   CHAR16            *LoadOptions;
+   BOOLEAN           Enabled;
+} LEGACY_ENTRY;
+
+/*
+#ifdef __MAKEWITH_TIANO
 typedef struct {
    REFIT_MENU_ENTRY me;
-   REFIT_VOLUME     *Volume;
-   CHAR16           *LoadOptions;
+   BDS_COMMON_OPTION *BdsOption;
    BOOLEAN          Enabled;
-} LEGACY_ENTRY;
+} LEGACY_ENTRY_NON_MAC;
+#endif // __MAKEWITH_TIANO
+*/
 
 typedef struct {
    BOOLEAN     TextOnly;
index 8f4cf39013f550e913d568b40db5c5cd4a504040..a228096ddb56522f51e409fefcbe85c3c1773e8e 100644 (file)
 #include "driver_support.h"
 #include "../include/syslinux_mbr.h"
 
+#ifdef __MAKEWITH_TIANO
+#include "../EfiLib/BdsHelper.h"
+#endif // __MAKEWITH_TIANO
+
 // 
 // variables
 
@@ -110,7 +114,7 @@ static VOID AboutrEFInd(VOID)
 
     if (AboutMenu.EntryCount == 0) {
         AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
-        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.4.5");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.4.5.2");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
@@ -1157,6 +1161,15 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry)
     FinishExternalScreen();
 } /* static VOID StartLegacy() */
 
+// Start a device on a non-Mac using the EFI_LEGACY_BIOS_PROTOCOL
+#ifdef __MAKEWITH_TIANO
+static VOID StartLegacyNonMac(IN LEGACY_ENTRY *Entry)
+{
+    BdsLibConnectDevicePath (Entry->BdsOption->DevicePath);
+    BdsLibDoLegacyBoot(Entry->BdsOption);
+}
+#endif // __MAKEWITH_TIANO
+
 static LEGACY_ENTRY * AddLegacyEntry(IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume)
 {
     LEGACY_ENTRY            *Entry, *SubEntry;
@@ -1212,6 +1225,112 @@ static LEGACY_ENTRY * AddLegacyEntry(IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Vo
     return Entry;
 } /* static LEGACY_ENTRY * AddLegacyEntry() */
 
+
+#ifdef __MAKEWITH_TIANO
+/**
+    Create a rEFInd boot option from a Legacy BIOS protocol option.
+*/
+static LEGACY_ENTRY * AddLegacyEntryNonMac(BDS_COMMON_OPTION *BdsOption, IN UINT16 DiskType)
+{
+    LEGACY_ENTRY            *Entry, *SubEntry;
+    REFIT_MENU_SCREEN       *SubScreen;
+    CHAR16                  ShortcutLetter = 0;
+    CHAR16 *LegacyDescription = BdsOption->Description;
+
+    // prepare the menu entry
+    Entry = AllocateZeroPool(sizeof(LEGACY_ENTRY));
+    Entry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
+    SPrint(Entry->me.Title, 255, L"Boot legacy target %s", LegacyDescription);
+    Entry->me.Tag          = TAG_LEGACY_NON_MAC;
+    Entry->me.Row          = 0;
+    Entry->me.ShortcutLetter = ShortcutLetter;
+    Entry->me.Image        = LoadOSIcon(L"legacy", L"legacy", TRUE);
+    Entry->LoadOptions     = (DiskType == BBS_CDROM) ? L"CD" :
+                             ((DiskType == BBS_USB) ? L"USB" : L"HD");
+    Entry->me.BadgeImage   = NULL;
+    Entry->BdsOption          = BdsOption; 
+    Entry->Enabled         = TRUE;
+
+    // create the submenu
+    SubScreen = AllocateZeroPool(sizeof(REFIT_MENU_SCREEN));
+    SubScreen->Title = AllocateZeroPool(256 * sizeof(CHAR16));
+    SPrint(SubScreen->Title, 255, L"No boot options for legacy target");
+    SubScreen->TitleImage = Entry->me.Image;
+
+    // default entry
+    SubEntry = AllocateZeroPool(sizeof(LEGACY_ENTRY));
+    SubEntry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
+    SPrint(SubEntry->me.Title, 255, L"Boot %s", LegacyDescription);
+    SubEntry->me.Tag          = TAG_LEGACY_NON_MAC;
+    Entry->BdsOption          = BdsOption; 
+    AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+
+    AddMenuEntry(SubScreen, &MenuEntryReturn);
+    Entry->me.SubScreen = SubScreen;
+    AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
+    return Entry;
+} /* static LEGACY_ENTRY * AddLegacyEntryNonMac() */
+
+/**
+    Scan for legacy BIOS targets on machines that implement EFI_LEGACY_BIOS_PROTOCOL.
+    In testing, protocol has not been implemented on Macs but has been
+    implemented on several Dell PCs.
+*/
+static VOID ScanLegacyNonMac()
+{
+    EFI_STATUS                Status;
+    EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
+    EFI_GUID EfiLegacyBootProtocolGuid     = { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }};
+    EFI_GUID EfiGlobalVariableGuid     = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }};
+    UINT16                    *BootOrder = NULL;
+    UINTN                     Index = 0;
+    UINT16                    BootOption[10];
+    UINTN                     BootOrderSize = 0;
+    CHAR16            Buffer[20];
+    BDS_COMMON_OPTION *BdsOption;
+    LIST_ENTRY        TempList;
+    BBS_BBS_DEVICE_PATH * BbsDevicePath = NULL;
+
+    InitializeListHead (&TempList);
+    ZeroMem (Buffer, sizeof (Buffer));
+
+    // If LegacyBios protocol is not implemented on this platform, then
+    //we do not support this type of legacy boot on this machine.
+    Status = gBS->LocateProtocol (&EfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios);
+    if (EFI_ERROR (Status))
+        return;
+
+    // Grab the boot order
+    BootOrder = BdsLibGetVariableAndSize (L"BootOrder", &EfiGlobalVariableGuid, &BootOrderSize);
+    if (BootOrder == NULL) {
+        BootOrderSize = 0;
+    }
+
+    Index = 0;
+    while (Index < BootOrderSize / sizeof (UINT16))
+    {
+        // Grab each boot option variable from the boot order, and convert
+        // the variable into a BDS boot option
+        UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
+        BdsOption = BdsLibVariableToOption (&TempList, BootOption);
+
+        //Print(L"Option description = '%s'\n", BdsOption->Description);
+        BbsDevicePath = (BBS_BBS_DEVICE_PATH *)BdsOption->DevicePath;
+
+        // Only add the entry if it is of a supported type (e.g. USB, HD)
+        // See BdsHelper.c for currently supported types
+        if(IsBbsDeviceTypeSupported(BbsDevicePath->DeviceType))
+        {
+           // TODO: Find/build REFIT_VOLUME structure for volume and pass instead of NULL
+           AddLegacyEntryNonMac(BdsOption, BbsDevicePath->DeviceType);
+        }
+        Index++;
+    }
+} /* static VOID ScanLegacyNonMac() */
+#else
+static VOID ScanLegacyNonMac(){}
+#endif // __MAKEWITH_TIANO
+
 static VOID ScanLegacyVolume(REFIT_VOLUME *Volume, UINTN VolumeIndex) {
    UINTN VolumeIndex2;
    BOOLEAN ShowVolume, HideIfOthersFound;
@@ -1460,6 +1579,7 @@ static VOID LoadDrivers(VOID)
        ConnectAllDriversToAllControllers();
 } /* static VOID LoadDrivers() */
 
+
 static VOID ScanForBootloaders(VOID) {
    UINTN i;
 
@@ -1489,6 +1609,9 @@ static VOID ScanForBootloaders(VOID) {
          case 'o': case 'O':
             ScanOptical();
             break;
+         case 'l': case 'L':
+            ScanLegacyNonMac();
+            break;
       } // switch()
    } // for
 
@@ -1578,6 +1701,7 @@ static VOID InitializeLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *System
    //    gImageHandle   = ImageHandle;
    gBS            = SystemTable->BootServices;
    //    gRS            = SystemTable->RuntimeServices;
+   gRT = SystemTable->RuntimeServices; // Some BDS functions need gRT to be set
    EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);
 
    InitializeConsoleSim();
@@ -1655,6 +1779,12 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
                 StartLegacy((LEGACY_ENTRY *)ChosenEntry);
                 break;
 
+#ifdef __MAKEWITH_TIANO
+            case TAG_LEGACY_NON_MAC: // Boot a legacy OS on a non-Mac
+                StartLegacyNonMac((LEGACY_ENTRY *)ChosenEntry);
+                break;
+#endif // __MAKEWITH_TIANO
+
             case TAG_TOOL:     // Start a EFI tool
                 StartTool((LOADER_ENTRY *)ChosenEntry);
                 break;