From 315c06865c0b4e3dfceec2107e6e12713813ea8a Mon Sep 17 00:00:00 2001 From: srs5694 Date: Sat, 15 Dec 2012 22:20:39 -0500 Subject: [PATCH] Ext4fs support; enable override of initrd in refind_linux.conf --- BUILDING.txt | 3 +- NEWS.txt | 4 ++ docs/refind/drivers.html | 11 +++-- filesystems/Make.tiano | 2 +- filesystems/Makefile | 6 ++- filesystems/VBoxFswParam.h | 69 ------------------------------- filesystems/fsw_base.h | 25 +++++------ filesystems/fsw_core.h | 2 +- filesystems/fsw_efi.c | 7 +--- filesystems/fsw_efi_base.h | 6 ++- filesystems/fsw_efi_lib.c | 2 - filesystems/hfs_format.h | 3 +- filesystems/test/fsw_posix_base.h | 19 +++++---- filesystems/test/lslr.c | 26 ++++++------ filesystems/test/lsroot.c | 11 ++--- install.sh | 2 + refind/config.c | 2 + refind/config.h | 1 + refind/main.c | 56 ++++++++++++------------- 19 files changed, 103 insertions(+), 154 deletions(-) delete mode 100644 filesystems/VBoxFswParam.h diff --git a/BUILDING.txt b/BUILDING.txt index e5501c2..a60279a 100644 --- a/BUILDING.txt +++ b/BUILDING.txt @@ -310,7 +310,8 @@ To build all the drivers, you can type "make fs" from the main directory, which builds the drivers and places copies in both the filesystems and drivers_{arch} subdirectories. If you want to build just one driver, you can change into the "filesystems" directory and type "make {fsname}", where -{fsname} is a filesystem name -- "ext2", "reiserfs", "iso9660", or "hfs". +{fsname} is a filesystem name -- "ext2", "ext4fs", "reiserfs", "iso9660", +or "hfs". To install drivers, you can type "make install" in the "filesystems" directory. This copies all the drivers to the diff --git a/NEWS.txt b/NEWS.txt index 7abbcc3..6a62e14 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,6 +1,10 @@ 0.5.2 (12/??/2012): ------------------- +- Added ext4fs driver! + +- Made "boot" the default value for "also_scan_dirs. + - Added identifying screen header to line editor. - Fixed bug that caused rEFInd's display to be mis-sized upon return diff --git a/docs/refind/drivers.html b/docs/refind/drivers.html index f20140a..b94291c 100644 --- a/docs/refind/drivers.html +++ b/docs/refind/drivers.html @@ -136,6 +136,11 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

used in the same way as the ReiserFS driver. Although it's called an "ext2fs" driver, it also works with ext3fs. +
  • Ext4fs—Stefan Agner modified the rEFIt/rEFInd ext2fs + driver so that it could handle ext4fs. I'm including this as a separate + driver from the ext2fs driver, although the ext4fs version seems to be + able to handle ext2fs and ext3fs, too.
  • +
  • ISO-9660—This driver originated with rEFIt's author, but he never released a final version. Its code was improved by Oracle for use in its VirtualBox product, and then further modified by the authors @@ -203,13 +208,13 @@ fs0: map -r

    Notes on Specific Drivers

    -

    I've tested several of the drivers described on this page on a handful of systems. The Pfisterer ext2fs driver (from any source) works on both ext2fs and ext3fs, but not on ext4fs—at least, not in my one test. (There may be options you can use when creating an ext4 filesystem that would enable the ext2fs driver to handle it, but if so I don't know what they are.) The ReiserFS driver is obviously useful only on ReiserFS partitions. (Reiser4 is not supported, as far as I know.) Given that these filesystems are getting a bit on in age by Linux standards, you might do well to use them on a separate Linux /boot partition; however, if you're willing to use ext3fs or ReiserFS on your root (/) filesystem, you can use the EFI drivers to read your kernel from it. Note that this assumes you use conventional partitions; to the best of my knowledge, there's no EFI driver for Linux's Logical Volume Manager (LVM) or Redundant Array of Independent Disks (RAID) configurations, so the EFI can't access filesystems stored in these ways.

    +

    I've tested several of the drivers described on this page on a handful of systems. The Pfisterer ext2fs driver (from any source) works on both ext2fs and ext3fs, but not on ext4fs—but Agner's derivative ext4fs driver handles ext4fs, so that's not a problem. The ReiserFS driver is obviously useful only on ReiserFS partitions. (Reiser4 is not supported, as far as I know.) Given that ext2fs, ext3fs, and ReiserFS are getting a bit on in age by Linux standards, you might do well to use them on a separate Linux /boot partition; however, if you're willing to use ext3fs or ReiserFS on your root (/) filesystem, you can use the EFI drivers to read your kernel from it. If you use ext4fs on your root (/) filesystem, you can use the ext4fs driver rather than a separate /boot partition. Note that this assumes you use conventional partitions; to the best of my knowledge, there's no EFI driver for Linux's Logical Volume Manager (LVM) or Redundant Array of Independent Disks (RAID) configurations, so the EFI can't access filesystems stored in these ways.

    -

    The Pfisterer ext2fs and ReiserFS drivers work, but they are a bit sluggish—particularly the ext2fs driver. The extent of the problem depends on the computer. In my tests so far, VirtualBox has fared the worst. On it, loading a Linux kernel with EFI stub loader from a FAT partition takes 2 seconds, from the moment of selecting the OS in rEFInd to the moment the kernel messages begin to appear. The equivalent time using ReiserFS or HFS+ is 20 seconds, and with ext2fs it's 200 seconds (that is, 3 minutes and 20 seconds). On a 32-bit Mac Mini, though, the speed problem is much less pronounced—my kernel loads in just 3 seconds from a ReiserFS partition and in 13 seconds from an ext2 filesystem. Speeds were similar with my newest computer, an ASUS P8H77-I board. Times with ext2fs on a UEFI PC with an Intel motherboard are in the 2–4 second range. If you try the ext2fs driver and it seems to hang, be patient; it may finally boot up. If so, and if the delay is too great for you to accept, you might consider using ReiserFS instead of ext2fs or ext3fs, at least if a change is practical. (For a /boot partition, it almost certainly is practical; you can back it up quite easily, create a fresh filesystem on it, and restore it. You may need to adjust your /etc/fstab entry for a new UUID value, though. As noted earlier, be sure to use notail as an option in /etc/fstab for ReiserFS if you want to read it from EFI.) You can even use HFS+ on a Linux /boot partition, although this makes the most sense on a Mac, which has its own EFI HFS+ driver. Of course, you can also create a FAT /boot partition and not deal with drivers at all. Mounting your ESP at /boot is a practical solution for many users.

    +

    The Pfisterer ReiserFS and ext2fs drivers work, but they are a bit sluggish—particularly the ext2fs driver. The Agner ext4fs driver, when handling an actual ext4 filesystem, is in-between these two drivers in speed. The extent of the problem depends on the computer. In my tests so far, VirtualBox has fared the worst. On it, loading a Linux kernel with EFI stub loader from a FAT partition takes 2 seconds, from the moment of selecting the OS in rEFInd to the moment the kernel messages begin to appear. The equivalent time using ReiserFS or HFS+ is 20 seconds, with ext4fs it's 75 seconds, and with ext2fs it's 200 seconds (that is, 3 minutes and 20 seconds). On a 32-bit Mac Mini, though, the speed problem is much less pronounced—my kernel loads in just 3 seconds from a ReiserFS partition and in 13 seconds from an ext2 filesystem. Speeds were similar with my newest computer, an ASUS P8H77-I board. Times with ext2fs on a UEFI PC with an Intel motherboard are in the 2–4 second range. If you try the ext2fs driver and it seems to hang, be patient; it may finally boot up. If so, and if the delay is too great for you to accept, you might consider using ext4fs or ReiserFS instead of ext2fs or ext3fs, at least if a change is practical. (For a /boot partition, it almost certainly is practical; you can back it up quite easily, create a fresh filesystem on it, and restore it. You may need to adjust your /etc/fstab entry for a new UUID value, though. As noted earlier, be sure to use notail as an option in /etc/fstab for ReiserFS if you want to read it from EFI.) You can even use HFS+ on a Linux /boot partition, although this makes the most sense on a Mac, which has its own EFI HFS+ driver. Of course, you can also create a FAT /boot partition and not deal with drivers at all. Mounting your ESP at /boot is a practical solution for many users.

    Since the ext2fs and ReiserFS drivers share a common origin, it should come as no surprise that they perform in much the same way no matter which version (rEFIt, Clover, or rEFInd) you use. The NTFS driver from the Clover Tools package is nice and speedy, so if for some reason you need to place a boot loader on an NTFS volume, this driver might be worth tracking down.

    -

    Although both ext2fs and ReiserFS are case-sensitive, these drivers treat them in a case-insensitive way. Symbolic links work, which opens up possibilities for configuration, such as using a single kernel binary for multiple Linux distributions, with a link in one subdirectory pointing to a file in another directory. (If you try this, though, be sure to use relative links, as in ../otherdist/bzImage.efi, at least if the partition is not Linux's root filesystem.)

    +

    Although ext2fs, ext3fs, ext4fs, and ReiserFS are all case-sensitive, these drivers treat them in a case-insensitive way. Symbolic links work, which opens up possibilities for configuration, such as using a single kernel binary for multiple Linux distributions, with a link in one subdirectory pointing to a file in another directory. (If you try this, though, be sure to use relative links, as in ../otherdist/bzImage.efi, at least if the partition is not Linux's root filesystem.)

    diff --git a/filesystems/Make.tiano b/filesystems/Make.tiano index 9eea221..f709b3e 100644 --- a/filesystems/Make.tiano +++ b/filesystems/Make.tiano @@ -62,7 +62,7 @@ BUILDME = $(DRIVERNAME)_$(FILENAME_CODE).efi OPTIMFLAGS = -fno-strict-aliasing -mno-red-zone -Wno-address -Os DEBUGFLAGS = -Wall -Wno-missing-braces -Wno-array-bounds -ffunction-sections -fdata-sections -CFLAGS = $(OPTIMFLAGS) -g -fshort-wchar -fno-stack-protector $(DEBUGFLAGS) -c -include AutoGen.h +CFLAGS = $(OPTIMFLAGS) -g -fshort-wchar -fno-stack-protector $(DEBUGFLAGS) -c -include AutoGen.h -DHOST_EFI_EDK2 prefix = /usr/bin/ CC = $(prefix)gcc diff --git a/filesystems/Makefile b/filesystems/Makefile index 2b24903..421d48f 100644 --- a/filesystems/Makefile +++ b/filesystems/Makefile @@ -8,7 +8,7 @@ INSTALL_DIR = /boot/efi/EFI/refind/drivers -FILESYSTEMS = ext2 reiserfs iso9660 hfs +FILESYSTEMS = ext2 reiserfs iso9660 hfs ext4 TEXTFILES = $(FILESYSTEMS:=*.txt) all: $(FILESYSTEMS) @@ -29,6 +29,10 @@ hfs: rm -f fsw_efi.o make DRIVERNAME=hfs -f Make.tiano +ext4: + rm -f fsw_efi.o + make DRIVERNAME=ext4 -f Make.tiano + # utility rules clean: diff --git a/filesystems/VBoxFswParam.h b/filesystems/VBoxFswParam.h deleted file mode 100644 index 0c44f89..0000000 --- a/filesystems/VBoxFswParam.h +++ /dev/null @@ -1,69 +0,0 @@ -/* $Id: VBoxFswParam.h 29125 2010-05-06 09:43:05Z vboxsync $ */ -/** @file - * VBoxFswParam.h - */ - -/* - * Copyright (C) 2010 Oracle Corporation - * - * This file is part of VirtualBox Open Source Edition (OSE), as - * available from http://www.virtualbox.org. This file is free software; - * you can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) as published by the Free Software - * Foundation, in version 2 as it comes in the "COPYING" file of the - * VirtualBox OSE distribution. VirtualBox OSE is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - */ - -#ifndef VBOXFSPARAM_H -#define VBOXFSPARAM_H -/* - * Here is common declarations for EDK<->EDK2 compatibility - */ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -# define BS gBS -# define PROTO_NAME(x) gEfi ## x ## Guid -# define GUID_NAME(x) gEfi ## x ## Guid - -# define EFI_FILE_HANDLE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION -# define SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL -# define EFI_FILE_SYSTEM_VOLUME_LABEL_INFO EFI_FILE_SYSTEM_VOLUME_LABEL -# define EFI_SIGNATURE_32(a, b, c, d) SIGNATURE_32(a, b, c, d) -# define DivU64x32(x,y,z) DivU64x32((x),(y)) - - -// INTN CompareGuidEdk1( -// IN EFI_GUID *Guid1, -// IN EFI_GUID *Guid2 -// ); - -//#define CompareGuid(x, y) CompareGuidEdk1((x),(y)) -# define HOST_EFI 1 -//# define FSW_DEBUG_LEVEL 3 - -int fsw_streq_ISO88591_UTF16(void *s1data, void *s2data, int len); -#endif diff --git a/filesystems/fsw_base.h b/filesystems/fsw_base.h index 0d5e7ba..31b78dc 100644 --- a/filesystems/fsw_base.h +++ b/filesystems/fsw_base.h @@ -51,30 +51,25 @@ #ifndef _FSW_BASE_H_ #define _FSW_BASE_H_ -//#define HOST_EFI 1 -#define VBOX -#ifdef VBOX -#include "VBoxFswParam.h" +#ifdef HOST_EFI_EDK2 +#define HOST_EFI #endif -//#include +#ifdef HOST_EFI +#include "fsw_efi_base.h" +#endif + +#ifdef HOST_POSIX +#include "test/fsw_posix_base.h" +#endif #ifndef FSW_DEBUG_LEVEL /** * Global debugging level. Can be set locally for the scope of a single * file by defining the macro before fsw_base.h is included. */ -#define FSW_DEBUG_LEVEL 0 -#endif - - -#ifdef HOST_EFI -#include "fsw_efi_base.h" -#endif - -#ifdef HOST_POSIX -#include "fsw_posix_base.h" +#define FSW_DEBUG_LEVEL 1 #endif // message printing diff --git a/filesystems/fsw_core.h b/filesystems/fsw_core.h index 4464cbd..db26fc7 100644 --- a/filesystems/fsw_core.h +++ b/filesystems/fsw_core.h @@ -58,7 +58,7 @@ /** Maximum size for a path, specifically symlink target paths. */ -#ifndef VBOX +#ifndef HOST_EFI_EDK2 #define FSW_PATH_MAX (4096) #else /* Too big allocations are handled with alloca() */ diff --git a/filesystems/fsw_efi.c b/filesystems/fsw_efi.c index 1193684..7df71aa 100644 --- a/filesystems/fsw_efi.c +++ b/filesystems/fsw_efi.c @@ -57,11 +57,7 @@ #define DEBUG_LEVEL 0 #ifndef FSTYPE -#ifdef VBOX #error FSTYPE must be defined! -#else -#define FSTYPE ext2 -#endif #endif #define DEBUG_VBFS 1 @@ -192,7 +188,8 @@ EFI_STATUS EFIAPI fsw_efi_main(IN EFI_HANDLE ImageHandle, { EFI_STATUS Status; -#ifndef VBOX +#ifndef HOST_EFI_EDK2 + // Not available in EDK2 toolkit InitializeLib(ImageHandle, SystemTable); #endif diff --git a/filesystems/fsw_efi_base.h b/filesystems/fsw_efi_base.h index 7c7af75..533be93 100644 --- a/filesystems/fsw_efi_base.h +++ b/filesystems/fsw_efi_base.h @@ -52,7 +52,11 @@ #ifndef _FSW_EFI_BASE_H_ #define _FSW_EFI_BASE_H_ -#ifndef VBOX +// If its EDK2 EFI Toolkit +#ifdef HOST_EFI_EDK2 +#include "fsw_efi_edk2_base.h" +#else +// Intel EFI Toolkit #include #include #define PROTO_NAME(x) x diff --git a/filesystems/fsw_efi_lib.c b/filesystems/fsw_efi_lib.c index 956e9ee..93a7ff1 100644 --- a/filesystems/fsw_efi_lib.c +++ b/filesystems/fsw_efi_lib.c @@ -140,7 +140,6 @@ VOID fsw_efi_strcpy(CHAR16 *Dest, struct fsw_string *src) } } -#ifdef VBOX int fsw_streq_ISO88591_UTF16(void *s1data, void *s2data, int len) { int i; @@ -157,6 +156,5 @@ int fsw_streq_ISO88591_UTF16(void *s1data, void *s2data, int len) return 1; } -#endif // EOF diff --git a/filesystems/hfs_format.h b/filesystems/hfs_format.h index 9b800e9..0512dfa 100644 --- a/filesystems/hfs_format.h +++ b/filesystems/hfs_format.h @@ -47,7 +47,8 @@ #ifndef __HFS_FORMAT__ #define __HFS_FORMAT__ -#if !defined(VBOX) && !defined(HOST_POSIX) +#if !defined(HOST_EFI_EDK2) && !defined(HOST_POSIX) +// Only available on Mac? and Intel EFI Toolkit? #include #include #endif diff --git a/filesystems/test/fsw_posix_base.h b/filesystems/test/fsw_posix_base.h index ee1d96c..0b7334b 100644 --- a/filesystems/test/fsw_posix_base.h +++ b/filesystems/test/fsw_posix_base.h @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -51,14 +52,14 @@ // types -typedef signed char fsw_s8; -typedef unsigned char fsw_u8; -typedef short fsw_s16; -typedef unsigned short fsw_u16; -typedef long fsw_s32; -typedef unsigned long fsw_u32; -typedef long long fsw_s64; -typedef unsigned long long fsw_u64; +typedef int8_t fsw_s8; +typedef uint8_t fsw_u8; +typedef int16_t fsw_s16; +typedef uint16_t fsw_u16; +typedef int32_t fsw_s32; +typedef uint32_t fsw_u32; +typedef int64_t fsw_s64; +typedef uint64_t fsw_u64; // allocation functions @@ -75,7 +76,7 @@ typedef unsigned long long fsw_u64; // message printing #define FSW_MSGSTR(s) s -#define FSW_MSGFUNC printf +#define FSW_MSGFUNC(str, ...) (fprintf(stderr, str, ##__VA_ARGS__)) // 64-bit hooks diff --git a/filesystems/test/lslr.c b/filesystems/test/lslr.c index d3e4e3c..bca4277 100644 --- a/filesystems/test/lslr.c +++ b/filesystems/test/lslr.c @@ -4,6 +4,7 @@ */ /*- + * Copyright (c) 2012 Stefan Agner * Copyright (c) 2006 Christoph Pfisterer * * Redistribution and use in source and binary forms, with or without @@ -35,6 +36,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define FSW_DEBUG_LEVEL 3 + #include "fsw_posix.h" @@ -58,19 +61,20 @@ static int listdir(struct fsw_posix_volume *vol, char *path, int level) dir = fsw_posix_opendir(vol, path); if (dir == NULL) { - printf("opendir(%s) call failed.\n", path); + fprintf(stderr, "opendir(%s) call failed.\n", path); return 1; } while ((dent = fsw_posix_readdir(dir)) != NULL) { for (i = 0; i < level*2; i++) - fputc(' ', stdout); - printf("%d %s\n", dent->d_type, dent->d_name); + fputc(' ', stderr); + fprintf(stderr, "%d %s\n", dent->d_type, dent->d_name); if (dent->d_type == DT_DIR) { snprintf(subpath, 4095, "%s%s/", path, dent->d_name); listdir(vol, subpath, level + 1); } } + fsw_posix_closedir(dir); return 0; @@ -84,9 +88,10 @@ static int catfile(struct fsw_posix_volume *vol, char *path) file = fsw_posix_open(vol, path, 0, 0); if (file == NULL) { - printf("open(%s) call failed.\n", path); + fprintf(stderr, "open(%s) call failed.\n", path); return 1; } + while ((r=fsw_posix_read(file, buf, sizeof(buf))) > 0) { int i; @@ -106,27 +111,24 @@ int main(int argc, char **argv) int i; if (argc != 2) { - printf("Usage: lslr \n"); + fprintf(stderr, "Usage: lslr \n"); return 1; } for (i = 0; fstypes[i]; i++) { vol = fsw_posix_mount(argv[1], fstypes[i]); if (vol != NULL) { - printf("Mounted as '%s'.\n", fstypes[i]->name.data); + fprintf(stderr, "Mounted as '%s'.\n", fstypes[i]->name.data); break; } } if (vol == NULL) { - printf("Mounting failed.\n"); + fprintf(stderr, "Mounting failed.\n"); return 1; } - //listdir(vol, "/System/Library/Extensions/udf.kext/", 0); - //listdir(vol, "/System/Library/Extensions/AppleACPIPlatform.kext/", 0); - //listdir(vol, "/System/Library/Extensions/", 0); - catfile(vol, "/System/Library/Extensions/AppleHPET.kext/Contents/Info.plist"); - //listdir(vol, "/", 0); + listdir(vol, "/boot/", 0); + catfile(vol, "/boot/vmlinuz-3.5.0-19-generic"); fsw_posix_unmount(vol); diff --git a/filesystems/test/lsroot.c b/filesystems/test/lsroot.c index bb2cba0..abbebff 100644 --- a/filesystems/test/lsroot.c +++ b/filesystems/test/lsroot.c @@ -38,10 +38,11 @@ #include "fsw_posix.h" -extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(ext2); extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(reiserfs); extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(iso9660); extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(hfs); +extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(ext2); +extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(ext4); int main(int argc, char **argv) { @@ -50,7 +51,7 @@ int main(int argc, char **argv) struct dirent *dent; if (argc != 2) { - printf("Usage: lsroot \n"); + fprintf(stderr, "Usage: lsroot \n"); return 1; } @@ -58,17 +59,17 @@ int main(int argc, char **argv) //vol = fsw_posix_mount(argv[1], &FSW_FSTYPE_TABLE_NAME(reiserfs)); vol = fsw_posix_mount(argv[1], &FSW_FSTYPE_TABLE_NAME(FSTYPE)); if (vol == NULL) { - printf("Mounting failed.\n"); + fprintf(stderr, "Mounting failed.\n"); return 1; } //dir = fsw_posix_opendir(vol, "/drivers/net/"); dir = fsw_posix_opendir(vol, "/"); if (dir == NULL) { - printf("opendir call failed.\n"); + fprintf(stderr, "opendir call failed.\n"); return 1; } while ((dent = fsw_posix_readdir(dir)) != NULL) { - printf("- %s\n", dent->d_name); + fprintf(stderr, "- %s\n", dent->d_name); } fsw_posix_closedir(dir); fsw_posix_unmount(vol); diff --git a/install.sh b/install.sh index e10a178..cb0d6d3 100755 --- a/install.sh +++ b/install.sh @@ -186,6 +186,8 @@ CopyDrivers() { case $BootFS in ext2 | ext3) DriverType="ext2" ;; + ext4) DriverType="ext4" + ;; reiserfs) DriverType="reiserfs" ;; hfsplus) DriverType="hfs" diff --git a/refind/config.c b/refind/config.c index 2f314e8..3831e4c 100644 --- a/refind/config.c +++ b/refind/config.c @@ -345,6 +345,8 @@ VOID ReadConfig(CHAR16 *FileName) // Set a few defaults only if we're loading the default file. if (StriCmp(FileName, CONFIG_FILE_NAME) == 0) { + MyFreePool(GlobalConfig.AlsoScan); + GlobalConfig.AlsoScan = StrDuplicate(ALSO_SCAN_DIRS); MyFreePool(GlobalConfig.DontScanDirs); GlobalConfig.DontScanDirs = StrDuplicate(SelfDirPath); MyFreePool(GlobalConfig.DontScanFiles); diff --git a/refind/config.h b/refind/config.h index ce3f880..bc211a9 100644 --- a/refind/config.h +++ b/refind/config.h @@ -79,6 +79,7 @@ typedef struct { #define CONFIG_FILE_NAME L"refind.conf" #define DONT_SCAN_FILES L"shim.efi,MokManager.efi,TextMode.efi,ebounce.efi,GraphicsConsole.efi" +#define ALSO_SCAN_DIRS L"boot" EFI_STATUS ReadFile(IN EFI_FILE_HANDLE BaseDir, CHAR16 *FileName, REFIT_FILE *File, UINTN *size); VOID ReadConfig(CHAR16 *FileName); diff --git a/refind/main.c b/refind/main.c index 4a5c0cb..05d15be 100644 --- a/refind/main.c +++ b/refind/main.c @@ -118,7 +118,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.5.1.5"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.5.1.6"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith"); @@ -455,6 +455,22 @@ LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry) { return (NewEntry); } // LOADER_ENTRY *InitializeLoaderEntry() +// Adds InitrdPath to Options, but only if Options doesn't already include an +// initrd= line. Done to enable overriding the default initrd selection in a +// refind_linux.conf file's options list. +// Returns a pointer to a new string. The calling function is responsible for +// freeing its memory. +static CHAR16 *AddInitrdToOptions(CHAR16 *Options, CHAR16 *InitrdPath) { + CHAR16 *NewOptions; + + NewOptions = StrDuplicate(Options); + if ((InitrdPath != NULL) && !StriSubCmp(L"initrd=", Options)) { + MergeStrings(&NewOptions, L"initrd=", L' '); + MergeStrings(&NewOptions, InitrdPath, 0); + } + return NewOptions; +} // CHAR16 *AddInitrdToOptions() + // Prepare a REFIT_MENU_SCREEN data structure for a subscreen entry. This sets up // the default entry that launches the boot loader using the same options as the // main Entry does. Subsequent options can be added by the calling function. @@ -463,7 +479,7 @@ LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry) { // Returns a pointer to the new subscreen data structure, or NULL if there // were problems allocating memory. REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) { - CHAR16 *FileName, *Temp = NULL; + CHAR16 *FileName, *MainOptions = NULL; REFIT_MENU_SCREEN *SubScreen = NULL; LOADER_ENTRY *SubEntry; @@ -479,12 +495,9 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { SubEntry->me.Title = L"Boot using default options"; - if ((SubEntry->InitrdPath != NULL) && (StrLen(SubEntry->InitrdPath) > 0) && (!StriSubCmp(L"initrd", SubEntry->LoadOptions))) { - MergeStrings(&Temp, L"initrd=", 0); - MergeStrings(&Temp, SubEntry->InitrdPath, 0); - MergeStrings(&SubEntry->LoadOptions, Temp, L' '); - MyFreePool(Temp); - } // if + MainOptions = SubEntry->LoadOptions; + SubEntry->LoadOptions = AddInitrdToOptions(MainOptions, SubEntry->InitrdPath); + MyFreePool(MainOptions); AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } // if (SubEntry != NULL) } // if (SubScreen != NULL) @@ -583,18 +596,14 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { } else if (Entry->OSType == 'L') { // entries for Linux kernels with EFI stub loaders File = ReadLinuxOptionsFile(Entry->LoaderPath, Volume); if (File != NULL) { - if ((Temp = FindInitrd(Entry->LoaderPath, Volume)) != NULL) { - MergeStrings(&InitrdOption, L"initrd=", 0); - MergeStrings(&InitrdOption, Temp, 0); - } + Temp = FindInitrd(Entry->LoaderPath, Volume); TokenCount = ReadTokenLine(File, &TokenList); // read and discard first entry, since it's FreeTokenLine(&TokenList, &TokenCount); // set up by InitializeSubScreen(), earlier.... while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { SubEntry = InitializeLoaderEntry(Entry); SubEntry->me.Title = StrDuplicate(TokenList[0]); MyFreePool(SubEntry->LoadOptions); - SubEntry->LoadOptions = StrDuplicate(TokenList[1]); - MergeStrings(&SubEntry->LoadOptions, InitrdOption, L' '); + SubEntry->LoadOptions = AddInitrdToOptions(TokenList[1], Temp); FreeTokenLine(&TokenList, &TokenCount); SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -680,18 +689,15 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { // kernel's directory; and if present, adds an initrd= option for an initial // RAM disk file with the same version number as the kernel file. static CHAR16 * GetMainLinuxOptions(IN CHAR16 * LoaderPath, IN REFIT_VOLUME *Volume) { - CHAR16 *Options = NULL, *InitrdName, *InitrdOption = NULL; + CHAR16 *Options = NULL, *InitrdName, *FullOptions = NULL; Options = GetFirstOptionsFromFile(LoaderPath, Volume); InitrdName = FindInitrd(LoaderPath, Volume); - if (InitrdName != NULL) { - MergeStrings(&InitrdOption, L"initrd=", 0); - MergeStrings(&InitrdOption, InitrdName, 0); - } // if - MergeStrings(&Options, InitrdOption, ' '); - MyFreePool(InitrdOption); + FullOptions = AddInitrdToOptions(Options, InitrdName); + + MyFreePool(Options); MyFreePool(InitrdName); - return (Options); + return (FullOptions); } // static CHAR16 * GetMainLinuxOptions() // Sets a few defaults for a loader entry -- mainly the icon, but also the OS type @@ -747,12 +753,6 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME } else if (StriCmp(FileName, L"e.efi") == 0 || StriCmp(FileName, L"elilo.efi") == 0 || StriSubCmp(L"elilo", FileName)) { MergeStrings(&OSIconName, L"elilo,linux", L','); Entry->OSType = 'E'; -// if (secure_mode()) { // hack to enable ELILO to boot in secure mode -// Temp = StrDuplicate(L"-C "); -// MergeStrings(&Temp, PathOnly, 0); -// MergeStrings(&Temp, L"elilo.conf", L'\\'); -// Entry->LoadOptions = Temp; -// } if (ShortcutLetter == 0) ShortcutLetter = 'L'; Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO; -- 2.39.2