From: Stefan Agner
Date: Thu, 20 Dec 2012 18:39:07 +0000 (+0100)
Subject: Merge branch 'master' of git://git.code.sf.net/p/refind/code
X-Git-Url: https://code.delx.au/refind/commitdiff_plain/d2370de648f795ccdf7fe76786c9516568cbe529?hp=04c467b8a01b0780621d63dafb9ac898a62cf824
Merge branch 'master' of git://git.code.sf.net/p/refind/code
---
diff --git a/BUILDING.txt b/BUILDING.txt
index e5501c2..b69df9b 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", "ext4", "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/CREDITS.txt b/CREDITS.txt
index d8efcde..469d663 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -52,3 +52,6 @@ I've incorporated into the current version. Specifically:
* The code for editing boot options (cursor_left(), cursor_right(), and
line_edit() in screen.c) is taken from gummiboot.
+
+* Stefan Agner (stefan@agner.ch) turned the original ext2fs/ext3fs driver
+ into one that can read ext4fs.
diff --git a/NEWS.txt b/NEWS.txt
index c927700..e249ef8 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,6 +1,118 @@
-0.5.1 (??/??/201?):
+0.6.1 (12/??/2012):
-------------------
+- Added the "words" that make up a filesystem's label (delimited by spaces,
+ dashes, or underscores) to the list of bases used to search for OS icons.
+ For instance, if the filesystem's label is "Arch", rEFInd searches for
+ os_Arch.icns; if it's "Fedora 17", it searches for os_Fedora.icns and
+ os_17.icns; and if it's "NEW_GENTOO", it searches for os_NEW.icns and
+ os_GENTOO.icns.
+
+- Refined hints displays to be more context-sensitive, particularly in text
+ mode.
+
+- Instead of displaying a blank filesystem label when a filesystem has
+ none, rEFInd now displays the size and/or type of the filesystem, as in
+ "boot EFI\foo\bar.efi from 200 MiB ext3 volume" rather than "boot
+ EFI\foo\bar.efi from".
+
+- Fixed a bug that caused the screen to clear after displaying an error
+ message but before displaying the "Hit any key to continue" message when
+ a boot loader launch failed.
+
+0.6.0 (12/16/2012):
+-------------------
+
+- Fixed a memory allocation bug that could cause a program crash when
+ specifying certain values with the "also_scan_dirs", "dont_scan_volumes",
+ "dont_scan_dirs", "dont_scan_files", and "scan_driver_dirs" refind.conf
+ options.
+
+- Modified Linux kernel initrd-finding code so that if an initrd is
+ specified in refind_linux.conf, rEFInd will not add any initrd it finds.
+ This enables an override of the default initrd, and is likely to be
+ particularly helpful to Arch Linux users.
+
+- 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
+ from a program that set the resolution itself.
+
+- Adjusted "resolution" refind.conf parameter so that it can accept EITHER
+ a resolution as width and height OR a single digit as a UEFI mode number
+ (which is system-specific). This is done because some systems present the
+ same mode twice in their mode lists, perhaps varying in refresh rate,
+ monitor output, or some other salient characteristics; specifying the
+ mode number enables selecting the higher-numbered mode, whereas using
+ horizontal and vertical resolution values selects the lowest-numbered
+ mode.
+
+- Added "textmode" refind.conf parameter to set the text mode used in
+ text-only displays, and for the line editor and boot-time handoff
+ display even in graphics mode.
+
+- Fixed bug that caused tools (shell, etc.) to launch when they were
+ highlighted and F2 or Insert was pressed.
+
+- Added "editor" option to the "hideui" token in refind.conf, which
+ disables the boot options editor.
+
+- Added hints text to rEFInd main menu and sub-menus. This can be disabled
+ by setting the new "hints" option to the "hideui" token in refind.conf.
+
+- Added "boot with minimal options" entry to refind_linux.conf file
+ generated by install.sh. This entry boots without the options extracted
+ from the /etc/default/grub file.
+
+- Added keys subdirectory to main distribution, to hold public Secure
+ Boot/shim keys from known sources.
+
+- Changed install.sh --drivers option to --alldrivers, added new
+ --nodrivers option, and made the default on Linux to install the one
+ driver that's used on /boot (or the root filesystem if /boot isn't a
+ separate partition). Of course, this won't install a non-existent driver,
+ and it also won't work properly if run from an emergency disk unless you
+ mount a separate /boot partition at that location.
+
+- Fixed bug in install.sh that prevented creation of refind_linux.conf file
+ on Linux systems.
+
+0.5.1.1 (12/12/2012):
+---------------------
+
+- Fixed bug in install.sh that prevented it from working on OS X.
+
+0.5.1 (12/11/2012):
+-------------------
+
+- Added support for "0" options to "textonly" and "scan_all_linux_kernels"
+ to reverse the usual meaning of these tokens. This is useful for
+ including these options in a secondary configuration file called with the
+ new "include" token to override a setting set in the main file.
+
+- Added "include" token for refind.conf, to enable including a secondary
+ configuration file from a primary one.
+
+- Modified install.sh so that it creates a simple refind_linux.conf file in
+ /boot, if that file doesn't already exist and if install.sh is run from
+ Linux. If that directory happens to be on a FAT, HFS+, ext2fs, ext3fs, or
+ ReiserFS volume, and if the necessary drivers are installed, the result
+ is that rEFInd will detect the Linux installation with no further
+ configuration on many systems. (Some may still require tweaking of kernel
+ options, though; for instance, adding "dolvm" on Gentoo systems that use
+ LVM.)
+
+- Added --shim and --localkeys options to install.sh to help simplify setup
+ on systems with Secure Boot active.
+
+- Fixed (maybe) bug that caused resolution options to not be displayed on
+ recent Macs with GOP graphics when specifying an invalid resolution in
+ refind.conf.
+
- Fixed bug that caused some programs (EFI shells, in particular) to hang
when launching on some systems (DUET, in particular).
diff --git a/docs/refind/bootmode.html b/docs/refind/bootmode.html
index 15e5218..07fb6ea 100644
--- a/docs/refind/bootmode.html
+++ b/docs/refind/bootmode.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -108,7 +108,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
A casual reader might easily overlook this option, or misinterpret it to mean that the feature is much less important than it is. In fact, this particular motherboard offers very poor control over its EFI vs. BIOS booting features. (See my Web page on this EFI implementation for details.)
-Some manuals omit even mention of EFI, and instead refer to "legacy boot" or some similar term, referring to BIOS-style booting. Such references may imply that the firmware supports EFI booting if the "legacy boot" mode is disabled or restricted in some way.
+Some manuals omit even mention of EFI, and instead refer to "legacy boot" or some similar term, referring to BIOS-style booting. The firmware for my ASUS P8H77-I motherboard uses the technical term CSM, which of course will be baffling to the uninitiated. (I referred to it earlier. It's the Compatibility Support Module—in other words, the BIOS support code.) Such references may imply that the firmware supports EFI booting if the "legacy boot" mode is disabled or restricted in some way.
Understated EFI features often indicate a slapdash approach to EFI. Such systems sometimes implement EFI as a layer atop a conventional BIOS. More modern EFIs, though, completely replace the BIOS. Some manufacturers, such as ASUS and its sibling ASRock, are now actively promoting their more advanced EFI implementations. Such products often come with flashy new GUIs in their firmware.
diff --git a/docs/refind/configfile.html b/docs/refind/configfile.html
index dcf1fe1..2f33216 100644
--- a/docs/refind/configfile.html
+++ b/docs/refind/configfile.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -104,21 +104,25 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Another way to hide a boot loader is to move it into rEFInd's own directory. In order to keep rEFInd from showing up in its own menu, it ignores boot loaders in its own directory. This obviously includes the rEFInd binary file itself, but also anything else you might store there.
-In addition to hiding boot loaders, you can adjust their icons. You can do this in any of three ways for auto-detected boot loaders:
+In addition to hiding boot loaders, you can adjust their icons. You can do this in any of five ways for auto-detected boot loaders:
+- You can name an icon file after your boot loader, but with an extension of .icns. For instance, if you're using loader.efi, you would name the icon file loader.icns. (If you use the scan_all_linux_kernels option, you can give an icon for a Linux kernel without a .efi extension a name based on the kernel name but with a .icns extension—for instance, bzImage-3.3.2.icns will serve as the icon for the bzImage-3.3.2 kernel.) These icon files should be 128x128 images in Apple's ICNS format. You can create such files easily in OS X or convert PNG files to ICNS format with libicns.
+
- You can place a boot loader in a directory with a name that matches one of rEFInd's standard icons, which take names of the form os_name.icns. To use this icon, you would place the boot loader in the directory called name.
-- You can name an icon file after your boot loader, but with an extension of .icns. For instance, if you're using loader.efi, you would name the icon file loader.icns. (If you use the scan_all_linux_kernels option, you can give an icon for a Linux kernel without a .efi extension a name based on the kernel name but with a .icns extension—for instance, bzImage-3.3.2.icns will serve as the icon for the bzImage-3.3.2 kernel.) These icon files should be 128x128 images in Apple's ICNS format. You can create such files easily in OS X or convert PNG files to ICNS format with libicns.
+- You can give the filesystem from which the boot loader is loaded a name that matches the OS name component of the icon filename. For instance, if you call your boot filesystem CentOS, it matches the os_centos.icns icon. This match is performed on a word-by-word basis within the name, with "words" being delimited by spaces, dashes (-), and underscores (_). Thus, a volume called Debian-boot will match os_debian.icns or os_boot.icns.
- If you're booting OS X from its standard boot loader, or if you place a boot loader file in the root directory of a partition, you can create a file called .VolumeIcon.icns that holds an icon file. OS X uses this file for its volume icons, so rEFInd picks up these icons automatically, provided they include 128x128 bitmaps.
+- Certain boot loaders have hard-coded icons associated with them. For instance, filenames beginning with vmlinuz or bzImage acquire Linux "Tux" icons and the bootmgfw.efi loader acquires a Windows icon. For the most part, these are the associations you want to overcome with the preceding rules, but sometimes renaming a boot loader to a more conventional name is the better approach.
+
-As a special case, rEFInd assigns icons to the Windows and OS X boot loaders based on their conventional locations, so they get suitable icons even though they don't follow these rules.
+As a special case, rEFInd assigns icons to the Windows and OS X boot loaders based on their conventional locations, so they get suitable icons even if they don't follow these rules.
-In addition to the main OS tag icon, you can set the badge icon for a volume by creating a file called .VolumeBadge.icns in the root directory of a partition. This icon file must include a 32x32 bitmap. If present, it replaces the disk-type icons that are overlaid on the main OS icon. If you use this feature, the badge is applied to all the boot loaders read from the disk, not just those stored in the root directory or the Apple boot loader location. You could use this feature to set a custom badge for different specific disks or to help differentiate multiple OS X installations on one computer.
+In addition to the main OS tag icon, you can set the badge icon for a volume by creating a file called .VolumeBadge.icns in the root directory of a partition. This icon file must include a 32x32 bitmap. If present, it replaces the disk-type icons that are overlaid on the main OS icon. If you use this feature, the badge is applied to all the boot loaders read from the disk, not just those stored in the root directory or the Apple boot loader location. You could use this feature to set a custom badge for different specific disks or to help differentiate multiple OS X installations on one computer. If you don't want any badges, you can replace the three badge icons in the rEFInd icons subdirectory (vol_external.icns, vol_internal.icns, and vol_optical.icns) with a completely transparent badge. The transparent.icns file in the rEFInd icons directory may be used for this purpose.
Adjusting the Global Configuration
@@ -145,8 +149,8 @@ timeout 20
hideui |
- banner, label, singleuser, hwtest, arrows, or all |
- Removes the specified user interface features. banner removes the banner graphic, label removes the text description of each tag and the countdown timer, singleuser removes the single-user option from the Mac OS sub-menu, hwtest removes the Mac OS hardware test option, arrows removes the arrows to the right or left of the OS tags when rEFInd finds too many OSes to display simultaneously, and all removes all of these options. You can specify multiple parameters with this option. The default is to set none of these values. |
+ banner, label, singleuser, hwtest, arrows, hints, editor, or all |
+ Removes the specified user interface features. banner removes the banner graphic, label removes the text description of each tag and the countdown timer, singleuser removes the single-user option from the Mac OS sub-menu, hwtest removes the Mac OS hardware test option, arrows removes the arrows to the right or left of the OS tags when rEFInd finds too many OSes to display simultaneously, hints removes the brief description of what basic keypressed do, editor disables the options editor, and all removes all of these options. You can specify multiple parameters with this option. The default is to set none of these values. |
icons_dir |
@@ -175,13 +179,18 @@ timeout 20
textonly |
- None |
- rEFInd defaults to a graphical mode; however, if you prefer to do without the flashy graphics, you can run it in text mode by including this option. |
+ None or 0 |
+ rEFInd defaults to a graphical mode; however, if you prefer to do without the flashy graphics, you can run it in text mode by including this option. Passing any option but 0 causes text mode to be used; passing a 0 causes graphics mode to be used. (This could be useful if you want to override a text-mode setting in an included secondary configuration file.) |
+
+
+ textmode |
+ text mode number |
+ Sets the text-mode video resolution to be used in conjunction with textonly or for the line editor and program-launch screens. This option takes a single-digit code. Mode 0 is guaranteed to be present and should be 80x25. Mode 1 is supposed to be either invalid or 80x50, but some systems use this number for something else. Higher values are system-specific. If you set this option to an invalid value, rEFInd pauses during startup to tell you of that fact. Note that on some computers, setting this value without also using textonly results in an incorrect graphics video mode being set. Pressing the Esc key corrects the problem. |
resolution |
- Two integer values |
- Sets the video resolution used by rEFInd; takes a width and a height as options. For instance, resolution 1024 768 sets the resolution to 1024x768. If you set a resolution that doesn't work on a UEFI-based system, rEFInd displays a message along with a list of valid modes. On an system built around EFI 1.x (such as a Mac), setting an incorrect resolution fails silently; you'll get the system's default resolution. You'll also get the system's default resolution if you set either resolution value to 0 or if you pass anything but two numbers. (Note that passing a resolution with an x, as in 1024x768, will be interpreted as one option and so will cause the default resolution to be used.) Also, be aware that it is possible to set a valid resolution for your video card that's invalid for your monitor. If you do this, your monitor will go blank until you've booted an OS that resets the video mode. |
+ one or two integer values |
+ Sets the video resolution used by rEFInd; takes either a width and a height or a single UEFI video mode number as options. For instance, resolution 1024 768 sets the resolution to 1024x768. On UEFI systems, resolution 1 sets video mode 1, the resolution of which varies from system to system. If you set a resolution that doesn't work on a UEFI-based system, rEFInd displays a message along with a list of valid modes. On an system built around EFI 1.x (such as a Mac), setting an incorrect resolution fails silently; you'll get the system's default resolution. You'll also get the system's default resolution if you set both resolution values to 0 or if you pass anything but two numbers. (Note that passing a resolution with an x, as in 1024x768, will be interpreted as one option and so will cause the default resolution to be used.) Also, be aware that it is possible to set a valid resolution for your video card that's invalid for your monitor. If you do this, your monitor will go blank until you've booted an OS that resets the video mode. |
use_graphics_for |
@@ -200,13 +209,18 @@ timeout 20
scan_delay |
- Numeric (integer) value |
+ numeric (integer) value |
Imposes a delay before rEFInd scans for disk devices. Ordinarily this is not necessary, but on some systems, some disks (particularly external drives and optical discs) can take a few seconds to become available. If some of your disks don't appear when rEFInd starts but they do appear when you press the Esc key to re-scan, try uncommenting this option and setting it to a modest value, such as 2, 5, or even 10. The default is 0. |
also_scan_dirs |
directory path(s) |
- Adds the specified directory or directories to the directory list that rEFInd scans for EFI boot loaders when scanfor includes the internal, external, or optical options. Directories are specified relative to the filesystem's root directory. If this option is used, it's applied to all the filesystems that rEFInd scans. If a specified directory doesn't exist, rEFInd ignores it (no error results). |
+ Adds the specified directory or directories to the directory list that rEFInd scans for EFI boot loaders when scanfor includes the internal, external, or optical options. Directories are specified relative to the filesystem's root directory. If this option is used, it's applied to all the filesystems that rEFInd scans. If a specified directory doesn't exist, rEFInd ignores it (no error results). The default value is boot, which is useful for locating Linux kernels when you have an EFI driver for your Linux root (/) filesystem. |
+
+
+ dont_scan_volumes or don't_scan_volumes |
+ filesystem label(s) |
+ Adds the specified volume or volumes to a volume "blacklist"—these filesystems are not scanned for EFI boot loaders. This may be useful to keep unwanted EFI boot entries, such as for a Macintosh recovery partition, from appearing on the main list of boot loaders. |
dont_scan_dirs or don't_scan_dirs |
@@ -220,14 +234,19 @@ timeout 20
scan_all_linux_kernels |
- None |
- When set, causes rEFInd to add Linux kernels (files with names that begin with vmlinuz or bzImage) to the list of EFI boot loaders, even if they lack .efi filename extensions. The hope is that this will simplify use of rEFInd on distributions that provide kernels with EFI stub loader support but that don't give those kernels names that end in .efi. Of course, the kernels must still be stored on a filesystem that rEFInd can read, and in a directory that it scans. (Drivers and the also_scan_dirs options can help with those issues.) Note that this option can cause unwanted files to be improperly detected and given loader tags, such as older kernels without EFI stub loader support. Versions of rEFInd prior to 0.5.0 left this option commented out in the refind.conf-sample file, but as of version 0.5.0, this option is enabled in the default configuration file. The program default remains to not scan for such kernels, though, so you can delete or uncomment this option to keep them from appearing in your boot menu. |
+ None or 0 |
+ When set, causes rEFInd to add Linux kernels (files with names that begin with vmlinuz or bzImage) to the list of EFI boot loaders, even if they lack .efi filename extensions. The hope is that this will simplify use of rEFInd on distributions that provide kernels with EFI stub loader support but that don't give those kernels names that end in .efi. Of course, the kernels must still be stored on a filesystem that rEFInd can read, and in a directory that it scans. (Drivers and the also_scan_dirs options can help with those issues.) Note that this option can cause unwanted files to be improperly detected and given loader tags, such as older kernels without EFI stub loader support. Versions of rEFInd prior to 0.5.0 left this option commented out in the refind.conf-sample file, but as of version 0.5.0, this option is enabled in the default configuration file. The program default remains to not scan for such kernels, though, so you can delete or uncomment this option to keep them from appearing in your boot menu. Passing any option but 0 causes scans for all kernels to occur; passing a 0 causes these kernels to not be scanned. (This could be useful if you want to override a setting of scan_all_linux_kernels in an included secondary configuration file.) |
default_selection |
A substring of a boot loader's title; or a numeric position |
Sets the default boot OS based on the loader's title, which appears in the main menu beneath the icons when you select the loader. You can enter any substring of the title as the default_selection, so long as it's two or more characters in length. It's best to use a unique substring, since rEFInd stops searching when it finds the first match. Because rEFInd sorts entries within a directory in descending order by file modification time, if you specify a directory (or volume name, for loaders in a partition's root directory) as the default_selection, the most recent loader in that directory will be the default. One-character entries are matched against the first character of the title, except for digits, which refer to the numeric order of the boot loader entries. |
+
+ include |
+ filename |
+ Includes the specified file into the current configuration file. Essentially, the included file replaces the include line, so positioning of this token is important if the included file includes options that contradict those in the main file. The included file must reside in the same directory as the rEFInd binary and the main configuration file. This option is valid only in the main configuration file; included files may not include third-tier configuration files. |
+
Prior to version 0.2.4, rEFInd supported a token called disable, whose function partially overlapped with hideui. Version 0.2.4 merges many of the features of these two tokens into hideui and creates the new showtools option, which provides the remaining functionality in a more flexible way.
diff --git a/docs/refind/drivers.html b/docs/refind/drivers.html
index fb5852f..a881ff2 100644
--- a/docs/refind/drivers.html
+++ b/docs/refind/drivers.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 4/19/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -136,6 +136,21 @@ 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 can handle
+ ext2fs and ext3fs, too. (I may eventually retire the original ext2fs
+ driver, but I want to be conservative about this in case there's an
+ undiscovered problem with the new driver.) This driver has some
+ limitations. Most notably, for various reasons it maxes out at 16TiB
+ and won't mount any ext4 filesystem that's larger than this. It also
+ doesn't support the meta_bg option flag; if your filesystem
+ uses this flag, this driver refuses to read it. You can learn about
+ your ext2/3/4 filesystem features by typing dumpe2fs /dev/sda2 | grep features,
+ changing /dev/sda2 to your
+ filesystem's device.
+
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
@@ -160,7 +175,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
All of these drivers rely on filesystem wrapper code written by rEFIt's author, Christoph Phisterer. They all suffer from speed problems on some systems, as described later in "Notes on Specific Drivers;" however, these problems are very minor on most systems.
-
+
If you want to use one or more of these drivers, you can install them from the rEFInd binary package from the refind/drivers_arch directory, where arch is a CPU architecture code—x64 or ia32. The files are named after the filesystems they handle, such as ext2_x64.efi for the 64-bit ext2fs driver. You should copy the files for the filesystems you want to use to the drivers or drivers_arch subdirectory of the main rEFInd installation directory. (You may need to create this subdirectory.) Be careful to install drivers only for your own architecture. Attempting to load drivers for the wrong CPU type will cause a small delay at best, or may cause the computer to crash at worst. I've placed rEFInd's drivers in directories that are named to minimize this risk, but you should exercise care when copying driver files.
@@ -203,13 +218,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, ext4fs, 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.
-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/docs/refind/features.html b/docs/refind/features.html
index b9f41c3..086c889 100644
--- a/docs/refind/features.html
+++ b/docs/refind/features.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -111,7 +111,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Inclusion of drivers for the Linux ReiserFS and ext2 filesystems in the
main package. (These drivers are absent from rEFInd prior to version
- 0.4.0; and the rEFInd versions don't work on at least some Macs.)
+ 0.4.0.)
@@ -143,7 +143,7 @@ lack a usable CSM.
The ability to specify additional directories to scan for boot loaders and drivers (as of version 0.2.7).
-The ability to specify directories to not be scanned for boot loaders, even if they would ordinarily be scanned (as of version 0.4.2).
+The ability to specify volumes and directories to not be scanned for boot loaders, even if they would ordinarily be scanned (as of version 0.6.0 for volumes and 0.4.2 for directories).
The ability to re-scan boot loaders, to assist when changing removable media or after making a change to the configuration file with an EFI shell (as of version 0.3.5).
@@ -151,7 +151,7 @@ lack a usable CSM.
The ability to specify an additional icon storage directory, to assist in efforts to customize rEFInd's appearance (as of version 0.3.4).
-The ability to set the screen's resolution, within limits imposed by the EFI (as of rEFInd 0.3.0).
+The ability to set the screen's graphics resolution, within limits imposed by the EFI (as of rEFInd 0.3.0). Similarly, as of version 0.6.0, you can specify the text-mode resolution.
Proper handling of more OS options than can fit on the screen. (rEFIt displays an empty list in graphical mode when it detects too many OSes.)
@@ -167,9 +167,9 @@ lack a usable CSM.
An "exit" option (disabled by default), so that you can return to whatever shell or boot manager you used to launch rEFInd, should this ability be desirable. (This feature first appeared in rEFInd 0.2.4.)
-Drivers for ISO-9660 and HFS+, which are not included in rEFIt. (The ISO-9660 driver is based on code from the rEFIt project, but was never completed by its original author. It was completed by Oracle for VirtualBox.)
+Drivers for ISO-9660, HFS+, and ext4fs, which are not included in rEFIt. (The ISO-9660 driver is based on code from the rEFIt project, but was never completed by its original author. It was completed by Oracle for VirtualBox. The ext4fs driver is derived from the rEFIt ext2fs driver.)
-Beginning with version 0.5.0, the ability to "talk" to the shim boot loader to validate binaries supported by shim or its machine owner key (MOK) list when booting in EFI mode. As of version 0.5.0, this support is still crude and buggy; it should be considered an alpha-level feature at the moment.
+Beginning with version 0.5.0, the ability to "talk" to the shim boot loader to validate binaries supported by shim or its machine owner key (MOK) list when booting with Secure Boot active. As of version 0.6.0, this support is still crude and buggy; it should be considered an alpha-level feature at the moment.
diff --git a/docs/refind/getting.html b/docs/refind/getting.html
index 3da81ee..4d81329 100644
--- a/docs/refind/getting.html
+++ b/docs/refind/getting.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/18/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -98,7 +98,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
- A
+ href="http://sourceforge.net/projects/refind/files/0.6.0/refind-src-0.6.0.zip/download">A
source code zip file—This is useful if you want to
compile the software locally. Note that I use Linux with the TianoCore EFI
@@ -109,7 +109,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
possible, but I've not attempted it.
- A
+ href="http://sourceforge.net/projects/refind/files/0.6.0/refind-bin-0.6.0.zip/download">A
binary zip file—Download this if you want to install
rEFInd and/or its filesystem drivers on an x86 or x86-64
computer and have no need to test rEFInd first by booting it on an
@@ -131,10 +131,10 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
either build.)
-->
-
+
- A
+ href="http://sourceforge.net/projects/refind/files/0.6.0/refind-cd-0.6.0.zip/download">A
CD-R image file—This download contains the same files as
the binary zip file, but you can burn it to a CD-R to test rEFInd
(and its filesystem drivers) without installing it first. (It boots on
diff --git a/docs/refind/index.html b/docs/refind/index.html
index bef175a..bcebfbb 100644
--- a/docs/refind/index.html
+++ b/docs/refind/index.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
diff --git a/docs/refind/installing.html b/docs/refind/installing.html
index 40c5f87..03f54cc 100644
--- a/docs/refind/installing.html
+++ b/docs/refind/installing.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -92,7 +92,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
-Once you've uncompressed a rEFInd binary zip file, you must install it to your computer's ESP (or conceivably to some other location). The details of how you do this depend on your OS and your computer (UEFI-based PC vs. Macintosh). The upcoming sections provide details. For Linux and Mac OS X, you can use the installation script, install.sh, which provides easy one-command installation on most systems. Occasionally this script will fail, though, so I also provide explicit instructions for Linux and Mac OS X. Installation under Windows also must be done manually. In some cases, you'll have to deviate from the default naming conventions, as described in a section on this topic. If you're upgrading rEFInd, see the section on upgrading. Finally, I describe how to install some additional components you might find useful. Note that this page describes installing the main rEFInd program; if you want to use the EFI filesystem drivers included with rEFInd, you should consult the page on using drivers with rEFInd.
+Once you've uncompressed a rEFInd binary zip file, you must install it to your computer's ESP (or conceivably to some other location). The details of how you do this depend on your OS and your computer (UEFI-based PC vs. Macintosh). The upcoming sections provide details. For Linux and Mac OS X, you can use the installation script, install.sh, which provides easy one-command installation on most systems. Occasionally this script will fail, though, so I also provide explicit instructions for Linux and Mac OS X. Installation under Windows also must be done manually. In some cases, you'll have to deviate from the default naming conventions, as described in a section on this topic. If you're upgrading rEFInd, see the section on upgrading. Finally, I describe how to install some additional components you might find useful.
Installing rEFInd Using install.sh under Linux or Mac OS X
@@ -195,13 +195,37 @@ Installation has completed successfully.
though; because of the popularity of dual boots with Windows on Macs,
the BIOS/legacy scans are enabled by default on Macs.
+- On Linux, install.sh checks the filesystem type of the
+ /boot directory and, if a matching filesystem driver is
+ available, installs it. Note that the "/boot directory" may be
+ on a separate partition or it may be part of your root (/)
+ filesystem, in which case the driver for your root filesystem is
+ installed. If install.sh detects that the filesystem in
+ question is ext2fs or ext3fs, it installs the ext4fs driver, which can
+ handle all three of these filesystem types. This feature is unlikely to
+ work properly from an emergency system, although it might if you have a
+ separate /boot partition and if you mount that partition at
+ /boot in your emergency system, and the ESP at
+ /boot/efi.
+
+- If you run install.sh on Linux and if
+ /boot/refind_linux.conf doesn't already exist,
+ install.sh creates this file and populates it with a few
+ sample entries. If /boot is on a FAT partition (or HFS+ on a
+ Mac), or if it's on an ext2fs, ext3fs, ext4fs, ReiserFS, or HFS+
+ partition and you install an appropriate driver, the
+ result is that rEFInd will detect your kernel and will probably boot it
+ correctly. Some systems will require manual tweaking to
+ refind_linux.conf, though—for instance, to add
+ dolvm to the boot options on Gentoo systems that use LVM.
+
In addition to these quirks, you should be aware of some options that install.sh supports to enable you to customize your installation in various ways. The syntax for install.sh is as follows:
-install.sh [--esp | --usedefault device-file] [--drivers] [--shim shim-filename] \
- [--localkeys]
+install.sh [--esp | --usedefault device-file] [--nodrivers | --alldrivers] \
+ [--shim shim-filename] [--localkeys]
The details of the options are summarized in Table 1. Using some of these options in unusual conditions can generate warnings and prompts to confirm your actions. In particular, using --shim or --localkeys when you're not booted in Secure Boot mode, or failing to use --shim when you are booted in Secure Boot mode, will generate a query and a request to confirm your installation. Consult the Managing Secure Boot page for more on this topic.
@@ -220,8 +244,12 @@ install.sh [--esp | --usedefault device-file] [--drive
You can install rEFInd to a disk using the default/fallback filename of EFI/BOOT/bootx64.efi (and EFI/BOOT/bootia32.efi, if the 32-bit build is available) using this option. The device-file should be an unmounted ESP, or at least a FAT partition, as in --usedefault /dev/sdc1. Your computer's NVRAM entries will not be modified when installing in this way. The intent is that you can create a bootable USB flash drive or install rEFInd on a computer that tends to "forget" its NVRAM settings with this option. This option is mutually exclusive with --esp. |
- --drivers |
- Ordinarily install.sh does not install drivers; but when you specify this option, it does; it copies all the driver files for your architecture. You may want to remove unused driver files after you use this option, especially if your computer uses Secure Boot. |
+ --nodrivers |
+ Ordinarily install.sh attempts to install the driver required to read /boot on Linux. This attempt works only if you're using ext2fs, ext3fs, or ReiserFS on the relevant partition. If you want to forego this driver installation, pass the --nodrivers option. This option is the default on OS X or when you use --usedefault. |
+
+
+ --alldrivers |
+ When you specify this option, install.sh copies all the driver files for your architecture. You may want to remove unused driver files after you use this option, especially if your computer uses Secure Boot. |
--shim shim-filename |
@@ -261,7 +289,7 @@ Filesystem 1K-blocks Used Available Use% Mounted on
Type rm refind_ia32.efi to remove the IA32 binary if you're using an x86-64 (64-bit) system; or type rm refind_x64.efi to remove the x86-64 binary if you're using an x86 (32-bit) system. You can optionally rename the binary you keep as refind.efi, but this isn't required. (Note that you must keep the version that's the correct bit width for your EFI; if you've installed a 32-bit Linux on a 64-bit PC with a 64-bit EFI, you'd keep refind_x64.efi.
-Optionally, type rm -r drivers_ia32 to remove the x86 drivers from an x86-64 system, or rm -r drivers_x64 to remove the x86-64 drivers from a 32-bit x86 system. You may also want to remove some or all of the drivers for the architecture you are using; if you don't need them, they'll slow down the start process. See the page on drivers for more on this topic.
+Optionally, type rm -r drivers_ia32 to remove the x86 drivers from an x86-64 system, or rm -r drivers_x64 to remove the x86-64 drivers from a 32-bit x86 system. You may also want to remove some or all of the drivers for the architecture you are using. If you don't need them, they'll slow down the start process, and worse, if you're using Secure Boot, rEFInd can load just one shim/MOK-signed driver. See the page on drivers for more on this topic.
Rename the configuration file by typing mv refind.conf-sample refind.conf. Consult the Editing the rEFInd Configuration File page for information on how to adjust your options.
@@ -516,7 +544,7 @@ $ ioreg -l -p IODeviceTree | grep firmware-abi
Drivers—You can install drivers to extend the capabilities
of the EFI. rEFInd ships with filesystem drivers for ext2fs and
ReiserFS, which can enable you to boot a Linux kernel with EFI stub
- support from an ext2fs, ext3fs, or ReiserFS partition. (rEFInd also
+ support from an ext2fs, ext3fs, ext4fs, or ReiserFS partition. (rEFInd also
provides ISO-9660 and HFS+ drivers.) You can find additional drivers
from other sources, although they're still on the scarce side. See the
Using EFI Drivers page for more on this
@@ -550,6 +578,8 @@ $ ioreg -l -p IODeviceTree | grep firmware-abi
+Some sources suggest that delayed launches of rEFInd on Macs are more common when installing rEFInd to the ESP, so if you've done this, you could try re-installing it to your OS X boot partition.
+
Uninstalling rEFInd
diff --git a/docs/refind/linux.html b/docs/refind/linux.html
index 77cabc0..5e9aa88 100644
--- a/docs/refind/linux.html
+++ b/docs/refind/linux.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/19/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -92,17 +92,160 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Windows and Mac OS X both provide relatively simple EFI boot loader programs. Launch them, and if they're launched from the correct locations and have the correct files in place, they'll boot their respective OSes. This makes rEFInd's job easy; it just locates the boot loader program files and runs them.
-Under Linux, by contrast, things can get complicated. As detailed on my Managing EFI Boot Loaders for Linux page, several different EFI boot loaders for Linux exist, and all of them require configuration. If you're lucky, your distribution will have set up a Linux boot loader in a sensible way, in which case rEFInd should detect it and it will work as easily as a Windows or Mac OS X boot loader. If you're not lucky, though, you may need to configure it further. rEFInd offers options to help out with this task. Specifically, you can use a traditional Linux boot loader or configure an EFI stub loader.
+Under Linux, by contrast, things can get complicated. As detailed on my Managing EFI Boot Loaders for Linux page, several different EFI boot loaders for Linux exist, and all of them require configuration. If you're lucky, your distribution will have set up a Linux boot loader in a sensible way, in which case rEFInd should detect it and it will work as easily as a Windows or Mac OS X boot loader. If you're not lucky, though, you may need to configure it further. rEFInd offers options to help out with this task. Naturally, rEFInd supports traditional Linux boot loaders. It works even better with the Linux EFI stub loader, so I provide instructions on starting with it. For those interested in manual configuration, I also provide detailed instructions on how the EFI stub support works and how to configure it.
+
Using a Traditional Linux Boot Loader
+
-I consider ELILO, GRUB Legacy, and GRUB 2 to be traditional Linux boot loaders. These programs all exist as EFI programs that are independent of the Linux kernel, but that can load a kernel and hand off control to it. All three programs have their own configuration files that reside in the same directory as the boot loader itself (or optionally elsewhere, in the case of GRUB 2).
+I consider ELILO, GRUB Legacy, and GRUB 2 to be traditional Linux boot loaders. These programs all exist independent of the Linux kernel, but they can load a kernel and hand off control to it. All three programs have their own configuration files that reside in the same directory as the boot loader itself (or optionally elsewhere, in the case of GRUB 2).
Ordinarily, rEFInd will detect these traditional boot loaders and provide main menu entries for them. If the boot loader exists in a directory with a name that matches a Linux distribution's icon filename, you'll automatically get a distribution-specific icon to refer to the boot loader.
If you prefer, you can disable automatic scanning and create an entry in refind.conf for your distribution, as described on the Configuring the Boot Manager page. This method is harder to set up but can be preferable if you want to customize your options.
-Using the EFI Stub Loader
+
+Using the EFI Stub Loader: A Quick Setup Guide
+
+
+The EFI stub loader is basic and reliable, but it requires some setup to use it on some computers. I describe three methods of using it: an easiest method for those with compatible partition and filesystem layouts, a quick test configuration for those without such a layout, and a long-term setup for those without the ideal setup.
+
+
+For Those With Foresight or Luck: The Easiest Method
+
+
+This method requires that your /boot directory, whether it's on a separate partition or is a regular directory in your root (/) filesystem, be readable by the EFI. At the moment, all EFI implementations can read FAT and Macs can read HFS+. By using drivers, you can make any EFI read HFS+, ISO-9660, ReiserFS, ext2fs, ext3fs, or ext4fs. Thus, if you use any of these filesystems on a regular partition (not an LVM or RAID configuration) that holds your kernels in /boot, you qualify for this easy method. The default partition layouts used by Ubuntu, Fedora, and many other distributions qualify, because they use one of these filesystems (usually ext4fs) in a normal partition or on a separate /boot partition. You must also have a 3.3.0 or later Linux kernel with EFI stub support, of course.
+
+If you installed rEFInd 0.6.0 or later with its install.sh script from your regular Linux installation, chances are everything's set up; you should be able to reboot and see your Linux kernels as boot options. If you installed manually, from OS X, or from an emergency system, though, you may need to do a couple of things manually:
+
+
+
+- Copy the relevant driver file for your filesystem and architecture to
+ the drivers or drivers_arch
+ subdirectory of the rEFInd installation directory on the ESP. You may
+ need to create this subdirectory, too.
+
+- Create a refind_linux.conf file in your /boot
+ directory. The mkrlconf.sh script that comes with rEFInd
+ should do this job, or you can do it manually as described later.
+
+
+
+When you reboot, you should see rEFInd options for your Linux kernels. If they work, your job is done, although you might want to apply some of the tweaks described in the maintenance-free setup section. If you have problems, you may need to adjust the refind_linux.conf file, as described in the detailed configuration section.
+
+
+Testing the EFI Stub Loader
+
+
+If you're not sure you want to use the EFI stub loader in the long term, you can perform a fairly quick initial test of it. This procedure assumes that you have access to a 3.3.0 or later Linux kernel with EFI stub support compiled into it. (Fedora 17, Ubuntu 12.10, and probably other distributions ship with such kernels.) Creating this configuration poses no risk to your current boot options, provided you don't accidentally delete existing files. The procedure for a quick test is:
+
+
+
+- Copy your kernel file (vmlinuz-*) and matching initial RAM
+ disk file (init*) from /boot to a subdirectory of
+ EFI on your ESP. Your distribution's directory there should
+ work fine. For instance, typing cp
+ /boot/vmlinuz-3.6.7-4.fc17.x86_64
+ /boot/initramfs-3.6.7-4.fc17.x86_64.img /boot/efi/EFI/redhat might
+ do the trick on a Fedora system, although you'll probably have to
+ adjust the version numbers. Note that the filename forms vary from one
+ distribution to another, so don't worry if yours look different from
+ these. Be sure that you match up the correct files by version number,
+ though.
+
+- Copy the /boot/refind_linux.conf file to the same directory to
+ which you copied your kernel. If this file doesn't exist, create it by
+ running (as root) the mkrlconf.sh script that came
+ with rEFInd.
+
+- Reboot. You should now see a new entry for launching the Linux kernel
+ that you copied. Try the option. If it works, great. If not, you may
+ need to adjust your refind_linux.conf file. See the detailed configuration section for a description of
+ this file's format. If the kernel begins to boot but complains that it
+ couldn't find its root filesystem, double-check the version numbers on
+ your kernel and initial RAM disk file, and check the root=
+ option in refind_linux.conf.
+
+
+
+You can continue to boot your computer with this type of configuration; however, the drawback is that you'll need to copy your kernel whenever it's updated. This can be a hassle. A better way is to configure you system so that the EFI, and therefore rEFInd, can read your Linux /boot directory, where most Linux distributions place their kernels.
+
+
+Configuring a Maintenance-Free Setup
+
+
+If your /boot directory happens to be on an XFS, JFS, or Btrfs partition that the EFI can't read, or it's tucked away in an LVM or RAID configuration that the EFI can't read, you won't be able to use the easiest solution. Fortunately, this problem can be overcome with relatively little fuss. Several variant procedures are possible, but I begin by describing one that will almost always work, although it's got some important caveats (described at the end). You should perform the following steps as root, or precede each of these commands with sudo:
+
+
+
+- Begin with your ESP mounted at /boot/efi, which is the most
+ common location. If it's not mounted there, type mount /dev/sda1 /boot/efi to do so (adjusting
+ /dev/sda1, if necessary), or mount it elsewhere and adjust the
+ paths in the following procedure as necessary.
+
+- Check the size of the ESP by typing df -h
+ /boot/efi. The ESP must be large enough to hold several Linux
+ kernels and initial RAM disk files—100MiB at a bare minimum, and
+ preferably 200–500MiB.
+
+- Check your /boot directory to be sure it contains no links or
+ other files that rely on Unix/Linux-style permissions or ownership. If
+ it does, don't proceed, or at least research these files further to
+ determine if you can work around the need for such permissions and
+ ownership.
+
+- Type cp -r /boot/* /boot/efi. You'll see an
+ error message about being unable to copy /boot/efi into
+ itself. Ignore this.
+
+- Type umount /boot/efi.
+
+- Edit /etc/fstab and change the mount point for
+ /boot/efi to /boot. If the ESP isn't present in
+ /etc/fstab, you must create an entry for it, with a mount
+ point of /boot.
+
+- Type mount -a to re-mount everything,
+ including /boot. Check that your normal /boot files
+ are all present, along with the new /boot/EFI directory, which
+ holds what used to be /boot/efi/EFI. If something seems to be
+ missing (other than /boot/efi with a lowercase efi),
+ then you should try to correct the problem.
+
+- If it doesn't already exist, create a file called
+ /boot/refind_linux.conf and populate it with kernel options,
+ as described later. If this file doesn't
+ already exist, the easiest way to create it is to run the
+ mkrlconf.sh script that comes with rEFInd 0.5.1 and
+ later.
+
+- Check your refind.conf file (presumably in
+ /boot/EFI/refind) to be sure that the
+ scan_all_linux_kernels line is uncommented. If it's not,
+ uncomment that line.
+
+- Optionally, type cp
+ /boot/EFI/refind/icons/os_name.icns /boot/.VolumeIcon.icns
+ to give loaders in /boot an icon for your distribution.
+
+- Reboot to test that this configuration works.
+
+
+
+Recall that in step #4, you copied the contents of /boot (as a safety measure), but you did not move them. Therefore, you ended up with two copies of your kernels and other /boot directory contents, with one copy hiding the other when you mounted the ESP at /boot. Once you've booted successfully and are sure all is working well, you can recover some disk space by unmounting /boot and deleting the contents of the underlying /boot directory on your root (/) filesystem. Be sure that the /boot partition is unmounted before you do this, though! Also, be sure to leave the /boot directory itself in place, even if it has no contents; the directory is needed as a mount point for the /boot partition. Note that GRUB 2 may stop working if you delete its files from the root filesystem's /boot/grub directory, so if you want to keep GRUB around, you should re-install it with the separate /boot partition mounted.
+
+Once this task is done, updates to your kernel will automatically be stored in the root directory of your ESP, where rEFInd will automatically detect them. Thus, the boot configuration becomes maintenance-free. The procedure as just described has some drawbacks, though. By placing your kernels in the root directory of your ESP, you render them vulnerable to any other OS with which you might be dual-booting. Your ESP must also be large enough to hold all your kernels. If you dual-boot with multiple Linux distributions, they might conceivably overwrite each others' kernels, and distinguishing one from another becomes more difficult.
+
+For these reasons, a variant of this procedure is desirable on some systems. Most of the steps are similar, but in this variant, you create a separate /boot partition that's independent of the ESP. This partition can use FAT, HFS+, ReiserFS, ext2fs, ext3fs, or ext4fs; but if you use any of the last five filesystems (four on Macs), you must install the matching EFI filesystem driver that ships with rEFInd. Creating the filesystem will normally require you to shrink an existing partition by a suitable amount (200–500MiB). Mount your new /boot partition at a temporary location, copy or move the current /boot files into it, unmount it, and add it to /etc/fstab as /boot.
+
+If your distribution already uses a separate /boot partition, but if it uses XFS or some other unsuitable filesystem, you can back it up, create a fresh FAT, HFS+, ReiserFS, ext2, ext3, or ext4 filesystem on it, and restore the original files. You'll probably need to adjust the UUID value in /etc/fstab to ensure that the computer mounts the new filesystem when you boot. If you use a separate non-ESP /boot partition, you'll probably want to continue mounting the ESP at /boot/efi.
+
+
+EFI Stub Loader Support Technical Details
+
The Linux EFI stub loader is a way to turn a Linux kernel into an EFI application. In a sense, the kernel becomes its own boot loader. This approach to booting Linux is very elegant in some ways, but as described on the page to which I just linked, it has its disadvantages, too. One challenge to booting in this way is that modern Linux installations typically require that the kernel be passed a number of options at boot time. These tell the kernel where the Linux root (/) filesystem is, where the initial RAM disk is, and so on. Without these options, Linux won't boot. These options are impossible for a generic boot loader to guess without a little help. It's possible to build a kernel with a default set of options, but this is rather limiting. Thus, rEFInd provides configuration options to help.
@@ -116,9 +259,9 @@ to modify its own rEFInd configuration; or the one that controls rEFInd
might set inappropriate options for another distribution. This is a problem
that's been a minor annoyance for years under BIOS, since the same
potential for poor configuration applies to LILO, GRUB Legacy, and GRUB 2
-on BIOS. The most reliable solution there is to chainload one boot loader
-to another. The same solution is possible under EFI, but rEFInd offers
-another possibility.
+on BIOS. The most reliable solution under BIOS is to chainload one boot
+loader to another. The same solution is possible under EFI, but rEFInd
+offers another possibility.
rEFInd 0.2.1 and later supports semi-automatic Linux EFI stub loader detection. This feature works as part of the standard boot loader scan operation, but it extends it as follows:
@@ -131,9 +274,10 @@ another possibility.
with version 0.3.0, if you uncomment the
scan_all_linux_kernels option in refind.conf, rEFInd
will also scan for kernels without a .efi filename
- extension. This option is not the default, though, because it can pick
- up old kernels that lack EFI stub loader support and even non-kernel
- files.
+ extension. This option is uncommented by default, but if you comment it
+ out, delete it, or change it to read scan_all_linux_kernels 0,
+ rEFInd won't scan for kernels that lack .efi filename
+ extensions.
@@ -157,12 +301,16 @@ another possibility.
booting from an auto-detected kernel. It consists of a series of lines,
each of which consists of a label followed by a series of kernel
options. The first line sets default options, and subsequent lines set
- options that are accessible from the main menu tag's submenu
- screen.
+ options that are accessible from the main menu tag's submenu screen. If
+ you installed rEFInd 0.5.1 or later with the install.sh
+ script, that script created a sample refind_linux.conf file,
+ customized for your computer, in /boot. This file will work
+ without changes on many installations, but you may need to tweak it for
+ some.
-The intent of this system is that distribution maintainers can place their kernels, initial RAM disks, and a refind_linux.conf file in their own subdirectory on the ESP. rEFInd will detect their kernels and create one main menu entry for each kernel. Each entry will implement as many options as there are lines in the refind_linux.conf file. In this way, two or more distributions can each maintain their boot loader entries, without being too concerned about who maintains rEFInd as a whole.
+The intent of this system is that distribution maintainers can place their kernels, initial RAM disks, and a refind_linux.conf file in their own subdirectories on the ESP, on EFI-accessible /boot partitions, or in /boot directories on EFI-accessible Linux root (/) partitions. rEFInd will detect these kernels and create one main menu entry for each kernel. Each entry will implement as many options as there are lines in the refind_linux.conf file. In this way, two or more distributions can each maintain their boot loader entries, without being too concerned about who maintains rEFInd as a whole.
The scan_all_linux_kernels option is intended to help users and distribution maintainers when rEFInd is used in conjunction with a Linux filesystem driver for EFI or when the ESP is mounted as the Linux /boot partition. In these cases, if all the kernels in Linux's /boot directory include EFI stub loader support, rEFInd will automatically detect and use kernels installed in the usual way, such as via an automatic system update. You won't even need to move or rename your kernels. You will need to set up a refind_linux.conf file and you may need to install a driver or set the also_scan_dirs option in refind.conf; but these are one-time requirements. Set up in this way, ongoing maintenance to handle kernel updates drops to zero!
@@ -179,12 +327,14 @@ total 17943
When rEFInd scans this directory, it will find two EFI boot loaders in EFI/ubuntu: grubx64.EFI and bzImage-3.3.0.efi. rEFInd will create two main-menu tags for these two loaders, one of which will launch Ubuntu's standard GRUB and the other of which will launch the 3.3.0 kernel file directly. The refind_linux.conf file contains a list of labels and options:
+
-"Boot with defaults" "root=/dev/sda3 ro quiet splash vt.handoff=7"
+"Boot using default options" "root=/dev/sda3 ro quiet splash vt.handoff=7"
"Boot into single-user mode" "root=UUID=1cd95082-bce0-494c-a290-d2e642dd82b7 ro single"
"Boot without graphics" "root=UUID=1cd95082-bce0-494c-a290-d2e642dd82b7 ro"
# "Boot alternate install" "root=/dev/sdb9 ro quiet splash vt.handoff=7"
+
Ordinarily, both fields in this file must be enclosed in quotes. If you have to pass an option that includes quotes, you can do so by doubling up on them, as in "root=/dev/sdb9 my_opt=""this is it""", which passes root=/dev/sdb9 my_opt="this is it" to the shell. You can include as much white space as you like between options. You can also place comments in the file, or remove an option by commenting it out with a leading hash mark (#), as in the fourth line in this example.
@@ -195,7 +345,7 @@ total 17943
a refind_linux.conf file in the Linux kernel's directory."
border=2>
-Note that the first entry shown here takes a name that's set in rEFInd rather than the one specified in the refind_linux.conf file. The remaining names match those specified in the file, though.
+To assist in initial configuration, rEFInd's install.sh script creates a sample refind_linux.conf file in /boot. This sample file defines three entries, the first two of which use the default GRUB options defined in /etc/default/grub and the last of which uses minimal options. The first entry boots normally and the second boots into single-user mode. If you want to create a new file, you can use the mkrlconf.sh script that comes with rEFInd. If you pass it the --force option, it will overwrite the existing /boot/refind_linux.conf file; otherwise it will create the file only if one doesn't already exist.
From a user's perspective, the submenus defined in this way work just like submenus defined via the submenuentry options in refind.conf, or like the submenus that rEFInd creates automatically for Mac OS X or ELILO. There are, however, limitations in what you can accomplish with this method:
diff --git a/docs/refind/revisions.html b/docs/refind/revisions.html
index 7ccd1c0..7e1c775 100644
--- a/docs/refind/revisions.html
+++ b/docs/refind/revisions.html
@@ -14,8 +14,7 @@
by Roderick W. Smith, rodsmith@rodsbooks.com
-Last Web page update: 12/6/2012
-
+Last Web page update: 12/16/2012
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -93,7 +92,13 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
-- 0.5.0 (12/5/2012)—I've focused on adding support for Matthew J. Garrett's shim program to this version of rEFInd; with this support, rEFInd is capable of launching Linux kernels and other programs signed with a suitable key while the computer is in Secure Boot mode. This initial release, however, requires significant manual configuration and has some known bugs and limitations. See the Managing Secure Boot page for details. Beyond this major new feature, this version includes several more minor improvements. These include a change to the resolution token so that it applies to text mode as well as to graphics mode; a bug fix that caused the line editor to blank out lines that were left unedited; a new dont_scan_files option to blacklist boot programs by filename; support for launching MokManager and Apple's Recovery HD partitions via tools (2nd-row) icons; new --usedefault and --drivers options to the install.sh script; a change of the esp installation script option to --esp; and the ability to use quote marks inside option strings by doubling them up.
+- 0.6.0 (12/16/2012)—The donation of a working ext4fs driver from Stefan Agner has prompted another big jump in the rEFInd version number, since this driver will greatly simplify installation on many systems: You may be able to simply run the install.sh script to get a working rEFInd that boots your Linux kernels directly, bypassing GRUB or ELILO. Other improvements in this version include bug fixes and minor changes to install.sh, the addition of hint text to the rEFInd main menu, the ability to disable the options editor via the editor option to hideui in refind.conf, a new textmode option to refind.conf to set the size of the text-mode display, a change to the code that adds your initial RAM disk to the boot options so that if you specify one manually (via refind_linux.conf), it will take precedence, and assorted obscure bug fixes. The NEWS.txt file goes into more details about many of these changes, as do the relevant pages of this HTML documentation.
+
+- 0.5.1.1 (12/12/2012)—This is a micro-update to fix a bug in the install.sh script that prevented it from working under OS X. Aside from that, and a few small documentation changes, this version changes nothing in rEFInd.
+
+- 0.5.1 (12/11/2012)—The most important changes to this version are to the install.sh script. It now supports two options, --shim and --localkeys, to aid in installation on a Secure Boot system. See the Installing rEFInd and Managing Secure Boot pages for details. The script also now creates a sample /boot/refind_linux.conf file to assist in setting up boots via the Linux EFI stub loader. All of these install.sh improvements work only in Linux. A separate mkrlconf.sh script creates a /boot/refind_linux.conf file if it doesn't exist, for help in post-installation configuration. In rEFInd itself, I've fixed the bug that caused ELILO to be unable to locate its configuration file when launched in Secure Boot mode and fixed a couple of more obscure bugs. I've also added an include token to refind.conf, to enable you to create a secondary configuration file (say, one managed by scripts while leaving the main file untouched; or one dedicated to manual boot stanzas).
+
+- 0.5.0 (12/6/2012)—I've focused on adding support for Matthew J. Garrett's shim program to this version of rEFInd; with this support, rEFInd is capable of launching Linux kernels and other programs signed with a suitable key while the computer is in Secure Boot mode. This initial release, however, requires significant manual configuration and has some known bugs and limitations. See the Managing Secure Boot page for details. Beyond this major new feature, this version includes several more minor improvements. These include a change to the resolution token so that it applies to text mode as well as to graphics mode; a bug fix that caused the line editor to blank out lines that were left unedited; a new dont_scan_files option to blacklist boot programs by filename; support for launching MokManager and Apple's Recovery HD partitions via tools (2nd-row) icons; new --usedefault and --drivers options to the install.sh script; a change of the esp installation script option to --esp; and the ability to use quote marks inside option strings by doubling them up.
- 0.4.7 (11/6/2012)—The most important new feature in this version is a boot options editor. From rEFInd's main menu, press Insert or F2 to see the options menu. Select one of the options and press Insert or F2 again and the screen switches to a text-mode display in which you can edit the options that will be passed to the boot loader. A second new feature is a new icon for gummiboot, which is another EFI boot manager. This version also alters the behavior of the scan_delay option, since I've been told that the previous version didn't work; the new one does. Finally, this version omits the space that followed boot options when booting most OSes. This behavior was inherited from rEFIt; a comment in the source code indicates it's needed by OS X, but I've been told it causes boot failures when launching Linux on some Macs. Thus, rEFInd now adds this space only when booting Mac OS X.
diff --git a/docs/refind/secureboot.html b/docs/refind/secureboot.html
index 7a5dc97..930296f 100644
--- a/docs/refind/secureboot.html
+++ b/docs/refind/secureboot.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 11/13/2012; last Web page update:
-12/8/2012, referencing rEFInd 0.5.0.1
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -232,7 +232,7 @@ described on this page currently supports only x86-64, not
At this point the computer may boot into its default OS, reboot, or perhaps even hang. When you reboot it, though, rEFInd should start up in Secure Boot mode. (You can verify this by selecting the About rEFInd tool in the main menu. Check the Platform item in the resulting screen; it should verify that Secure Boot is active.) You should now be able to launch any boot loader signed with a key recognized by the firmware or by shim (including any MOKs you've enrolled). If you want to manage keys in the future, rEFInd displays a new icon in the second (tools) row you can use to launch MokManager. (This icon appears by default if MokManager is installed, but if you edit showtools in refind.conf, you must be sure to include mok_tool as an option in order to gain access to it.)
-If you're using Ubuntu 12.10, you can't use its version of shim, but you can replace it with Garrett's shim. The problem is that Ubuntu's GRUB and kernel will then be signed by an unknown key. Unfortunately, I haven't found a suitable public key file on Ubuntu's distribution medium, so you may need to sign GRUB and/or your kernels with your own MOK. In principle, you should be able to use shim 0.2 or later from future distributions that include it; but you must be sure that whatever you use supports MokManager.
+If you're using Ubuntu 12.10, you can't use its version of shim, but you can replace it with Garrett's shim. If you do so, though, you'll have to add Ubuntu's public key as a MOK, at least if you intend to launch Ubuntu's version of GRUB or launch Ubuntu-provided signed kernels. Ubuntu's public key is available in the shim_0~20120906.bcd0a4e8-0ubuntu4.debian.tar.gz tarball, as canonical-uefi-ca.der. (The filename extensions .cer and .der are interchangeable for most purposes.) I've also included this key with rEFInd, in the refind/keys subdirectory of its package file. To use this key, copy it to your ESP and enroll it with MokManager. See this blog post for further details on Ubuntu 12.10's handling of Secure Boot. In principle, you should be able to use shim 0.2 or later from future distributions that include it; but you must be sure that whatever you use supports MokManager.
Managing Your MOKs
diff --git a/docs/refind/themes.html b/docs/refind/themes.html
index 884401b..3e370a1 100644
--- a/docs/refind/themes.html
+++ b/docs/refind/themes.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 4/19/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
diff --git a/docs/refind/todo.html b/docs/refind/todo.html
index 2fc86a5..d890e43 100644
--- a/docs/refind/todo.html
+++ b/docs/refind/todo.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
@@ -165,6 +165,13 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
from the partition data is harder than extracting the volume's
label or counting up the filesystem numbers.
+ - Currently, if a filesystem's label comes up empty, rEFInd
+ substitutes the size, so you get displays like boot
+ EFI\foo\bar.efi from 90 GiB volume. I'd like to add more
+ checks to substitute the GPT partition label if the
+ filesystem label comes up empty, or add a filesystem type
+ identifier to the size.
+
- The default_selection option in refind.conf could be improved by
supporting a list of default options, so that if the first item
isn't found, rEFInd will try to boot the second one in the list,
@@ -209,10 +216,6 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
/usr/local/UDK2010/MyWorkSpace/MdeModulePkg/Core/Dxe/Image/Image.c
for the reference UEFI implementation. -->
- - When launching ELILO in Secure Boot mode, ELILO can't find its
- configuration file. It's possible that a similar problem exists for
- other boot loaders, too.
-
- When setting a resolution higher than about 800x600 (or maybe even
640x480) in text mode, the text displayed by rEFInd, and on some
systems shells and other programs launched from rEFInd, is
@@ -270,14 +273,6 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
- - With the arrival of PCs preloaded with Windows 8 and with Secure
- Boot enabled, some way to cope is in order. I'm thinking of adding
- code to limit or prohibit booting of unsigned boot loaders if
- rEFInd detects that Secure Boot is active, and link with the Shim
- pre-bootloader to help handle signing and authentication. I need to
- research the technical details more, though.
-
- EFI supports network boots. rEFInd doesn't, but it would be nice if
it would.
@@ -313,9 +308,6 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
boot. Perhaps this could be done via a separate tool that could be
launched much like the shell or gptsync.
- - I'd like to give the user the ability to set custom options on a
- single-boot basis, similar to what's possible in GRUB.
-
- A way to set the color of the font would be useful for theming
purposes.
@@ -327,20 +319,15 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
written in a cross-platform GUI toolkit, so that a single code base
can be used on any of the major OSes.
- - A way to "source" one configuration file from another one would be
- helpful for some types of configuration scripts. (This would enable
- overriding options in a secondary file without modifying the
- default original file, for instance.)
-
Improvements to the EFI drivers:
- - Drivers for additional filesystems are required. Given the recent
- shift to ext4fs, that should be the priority; however, other Linux
- filesystems, UDF, and perhaps others would all be welcome
+
- Drivers for additional filesystems are desirable. Given the talk of
+ shifting to Btrfs, that should be the priority; however, other
+ Linux filesystems, UDF, and perhaps others would all be welcome
additions. Also along these lines, adding drivers for Linux LVM and
RAID setups would be useful, too.
diff --git a/docs/refind/using.html b/docs/refind/using.html
index 341045d..399352c 100644
--- a/docs/refind/using.html
+++ b/docs/refind/using.html
@@ -15,7 +15,7 @@
href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0
+12/16/2012, referencing rEFInd 0.6.0
I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
diff --git a/filesystems/fsw_efi.c b/filesystems/fsw_efi.c
index 7df71aa..3e96e62 100644
--- a/filesystems/fsw_efi.c
+++ b/filesystems/fsw_efi.c
@@ -76,7 +76,7 @@
/** Helper macro for stringification. */
#define FSW_EFI_STRINGIFY(x) #x
/** Expands to the EFI driver name given the file system type name. */
-#define FSW_EFI_DRIVER_NAME(t) L"rEFInd 0.5.0 " FSW_EFI_STRINGIFY(t) L" File System Driver"
+#define FSW_EFI_DRIVER_NAME(t) L"rEFInd 0.6.0 " FSW_EFI_STRINGIFY(t) L" File System Driver"
// function prototypes
diff --git a/icons/transparent.icns b/icons/transparent.icns
new file mode 100644
index 0000000..32ac2ed
Binary files /dev/null and b/icons/transparent.icns differ
diff --git a/install.sh b/install.sh
index 7e2fef4..e28fb41 100755
--- a/install.sh
+++ b/install.sh
@@ -12,7 +12,9 @@
# "--usedefault {devicefile}" to install as default
# (/EFI/BOOT/BOOTX64.EFI and similar) to the specified device
# (/dev/sdd1 or whatever) without registering with the NVRAM.
-# "--drivers" to install drivers along with regular files
+# "--alldrivers" to install all drivers along with regular files
+# "--nodrivers" to suppress driver installation (default in Linux is
+# driver used on /boot; --nodrivers is OS X default)
# "--shim {shimfile}" to install a shim.efi file for Secure Boot
# "--localkeys" to re-sign x86-64 binaries with a locally-generated key
#
@@ -27,7 +29,13 @@
#
# Revision history:
#
-# 0.5.1 -- Added --shim & --localkeys options
+# 0.6.0 -- Changed --drivers to --alldrivers and added --nodrivers option;
+# changed default driver installation behavior in Linux to install
+# the driver needed to read /boot (if available)
+# 0.5.1.2 -- Fixed bug that caused failure to generate refind_linux.conf file
+# 0.5.1.1 -- Fixed bug that caused script failure under OS X
+# 0.5.1 -- Added --shim & --localkeys options & create sample refind_linux.conf
+# in /boot
# 0.5.0 -- Added --usedefault & --drivers options & changed "esp" option to "--esp"
# 0.4.5 -- Fixed check for rEFItBlesser in OS X
# 0.4.2 -- Added notice about BIOS-based OSes & made NVRAM changes in Linux smarter
@@ -42,6 +50,7 @@
TargetDir=/EFI/refind
EtcKeysDir=/etc/refind.d/keys
LocalKeysBase="refind_local"
+RLConfFile="/boot/refind_linux.conf"
ShimSource="none"
TargetX64="refind_x64.efi"
TargetIA32="refind_ia32.efi"
@@ -54,7 +63,12 @@ DeleteRefindDir=0
GetParams() {
InstallToEspOnMac=0
- InstallDrivers=0
+ if [[ $OSName == "Linux" ]] ; then
+ # Install the driver required to read /boot, if it's available
+ InstallDrivers="boot"
+ else
+ InstallDrivers="none"
+ fi
while [[ $# -gt 0 ]]; do
case $1 in
--esp | --ESP) InstallToEspOnMac=1
@@ -65,16 +79,17 @@ GetParams() {
TargetIA32="bootia32.efi"
shift
;;
+ --localkeys) LocalKeys=1
+ ;;
--shim) ShimSource=$2
shift
;;
- --drivers) InstallDrivers=1
+ --drivers | --alldrivers) InstallDrivers="all"
;;
- --localkeys) LocalKeys=1
+ --nodrivers) InstallDrivers="none"
;;
- * ) echo "Usage: $0 [--esp | --usedefault {device-file}] [--drivers] "
- echo " [--localkeys] [--shim {shim-filename}]"
- echo "Aborting!"
+ * ) echo "Usage: $0 [--esp | --usedefault {device-file}] [--nodrivers | --alldrivers] "
+ echo " [--shim {shim-filename}] [--localkeys]"
exit 1
esac
shift
@@ -148,14 +163,44 @@ CopyShimFiles() {
# Copy the public keys to the installation medium
CopyKeys() {
if [[ $LocalKeys == 1 ]] ; then
- cp $EtcKeysDir/$LocalKeysBase.cer $InstallDir/$TargetDir
- cp $EtcKeysDir/$LocalKeysBase.crt $InstallDir/$TargetDir
- else
- cp $ThisDir/refind.cer $InstallDir/$TargetDir
- cp $ThisDir/refind.crt $InstallDir/$TargetDir
+ mkdir -p $InstallDir/$TargetDir/keys/
+ cp $EtcKeysDir/$LocalKeysBase.cer $InstallDir/$TargetDir/keys/
+ cp $EtcKeysDir/$LocalKeysBase.crt $InstallDir/$TargetDir/keys/
+# else
+# cp $ThisDir/refind.cer $InstallDir/$TargetDir/keys/
+# cp $ThisDir/refind.crt $InstallDir/$TargetDir/keys/
fi
} # CopyKeys()
+# Copy drivers from $RefindDir/drivers_$1 to $InstallDir/$TargetDir/drivers_$1,
+# honoring the $InstallDrivers condition. Must be passed a suitable
+# architecture code (ia32 or x64).
+CopyDrivers() {
+ if [[ $InstallDrivers == "all" ]] ; then
+ mkdir -p $InstallDir/$TargetDir/drivers_$1
+ cp $RefindDir/drivers_$1/*_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+ cp $ThisDir/drivers_$1/*_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+ elif [[ $InstallDrivers == "boot" && -x `which blkid` ]] ; then
+ BootPart=`df /boot | grep dev | cut -f 1 -d " "`
+ BootFS=`blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =`
+ DriverType=""
+ case $BootFS in
+ ext2 | ext3 | ext4) DriverType="ext4"
+ ;;
+ reiserfs) DriverType="reiserfs"
+ ;;
+ hfsplus) DriverType="hfs"
+ ;;
+ esac
+ if [[ -n $BootFS ]] ; then
+ echo "Installing driver for $BootFS (${DriverType}_$1.efi)"
+ mkdir -p $InstallDir/$TargetDir/drivers_$1
+ cp $RefindDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+ cp $ThisDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+ fi
+ fi
+}
+
# Copy the rEFInd files to the ESP or OS X root partition.
# Sets Problems=1 if any critical commands fail.
CopyRefindFiles() {
@@ -173,7 +218,7 @@ CopyRefindFiles() {
TargetShim="bootx64.efi"
CopyShimFiles
fi
- if [[ $InstallDrivers == 1 ]] ; then
+ if [[ $InstallDrivers == "all" ]] ; then
cp -r $RefindDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
cp -r $ThisDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
fi
@@ -184,22 +229,14 @@ CopyRefindFiles() {
if [[ $? != 0 ]] ; then
Problems=1
fi
- if [[ $InstallDrivers == 1 ]] ; then
- mkdir -p $InstallDir/$TargetDir/drivers_ia32
- cp $RefindDir/drivers_ia32/*_ia32.efi $InstallDir/$TargetDir/drivers_ia32/ 2> /dev/null
- cp $ThisDir/drivers_ia32/*_ia32.efi $InstallDir/$TargetDir/drivers_ia32/ 2> /dev/null
- fi
+ CopyDrivers ia32
Refind="refind_ia32.efi"
elif [[ $Platform == 'EFI64' ]] ; then
cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64
if [[ $? != 0 ]] ; then
Problems=1
fi
- if [[ $InstallDrivers == 1 ]] ; then
- mkdir -p $InstallDir/$TargetDir/drivers_x64
- cp $RefindDir/drivers_x64/*_x64.efi $InstallDir/$TargetDir/drivers_x64/ 2> /dev/null
- cp $ThisDir/drivers_x64/*_x64.efi $InstallDir/$TargetDir/drivers_x64/ 2> /dev/null
- fi
+ CopyDrivers x64
Refind="refind_x64.efi"
CopyKeys
if [[ $ShimSource != "none" ]] ; then
@@ -209,8 +246,8 @@ CopyRefindFiles() {
if [[ $LocalKeys == 0 ]] ; then
echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir"
mkdir -p $EtcKeysDir
- cp $ThisDir/refind.cer $EtcKeysDir
- cp $ThisDir/refind.crt $EtcKeysDir
+ cp $ThisDir/keys/refind.cer $EtcKeysDir
+ cp $ThisDir/keys/refind.crt $EtcKeysDir
fi
fi
else
@@ -228,6 +265,7 @@ CopyRefindFiles() {
if [[ $? != 0 ]] ; then
Problems=1
fi
+ cp -rf $ThisDir/keys $InstallDir/$TargetDir/
if [[ -f $InstallDir/$TargetDir/refind.conf ]] ; then
echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
echo "to avoid overwriting your customizations."
@@ -478,7 +516,7 @@ ReSignBinaries() {
cp $RefindDir/refind_ia32.efi $TempDir
cp -a $RefindDir/drivers_ia32 $TempDir 2> /dev/null
cp -a $ThisDir/drivers_ia32 $TempDir 2> /dev/null
- SignOneBinary $RefindDir/refind_x64.efi $ThisDir/refind_x64.efi
+ SignOneBinary $RefindDir/refind_x64.efi $TempDir/refind_x64.efi
for Driver in `ls $RefindDir/drivers_x64/*.efi $ThisDir/drivers_x64/*.efi 2> /dev/null` ; do
TempName=`basename $Driver`
SignOneBinary $Driver $TempDir/drivers_x64/$TempName
@@ -553,6 +591,29 @@ AddBootEntry() {
fi
} # AddBootEntry()
+# Create a minimal/sample refind_linux.conf file in /boot.
+GenerateRefindLinuxConf() {
+ if [[ ! -f $RLConfFile ]] ; then
+ if [[ -f /etc/default/grub ]] ; then
+ # We want the default options used by the distribution, stored here....
+ source /etc/default/grub
+ fi
+ RootFS=`df / | grep dev | cut -f 1 -d " "`
+ StartOfDevname=`echo $RootFS | cut -b 1-7`
+ if [[ $StartOfDevname == "/dev/sd" || $StartOfDevName == "/dev/hd" ]] ; then
+ # Identify root filesystem by UUID rather than by device node, if possible
+ Uuid=`blkid -o export $RootFS 2> /dev/null | grep UUID=`
+ if [[ -n $Uuid ]] ; then
+ RootFS=$Uuid
+ fi
+ fi
+ DefaultOptions="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
+ echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
+ echo "\"Boot to single-user mode\" \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
+ echo "\"Boot with minimal options\" \"ro root=$RootFS\"" >> $RLConfFile
+ fi
+}
+
# Controls rEFInd installation under Linux.
# Sets Problems=1 if something goes wrong.
InstallOnLinux() {
@@ -600,6 +661,7 @@ InstallOnLinux() {
CopyRefindFiles
if [[ $TargetDir != "/EFI/BOOT" ]] ; then
AddBootEntry
+ GenerateRefindLinuxConf
fi
} # InstallOnLinux()
@@ -609,14 +671,14 @@ InstallOnLinux() {
# install under OS X or Linux, depending on the detected platform.
#
-GetParams $@
OSName=`uname -s`
+GetParams $@
ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
RefindDir="$ThisDir/refind"
ThisScript="$ThisDir/`basename $0`"
if [[ `whoami` != "root" ]] ; then
echo "Not running as root; attempting to elevate privileges via sudo...."
- sudo $ThisScript $1 $2 $3 $4 $5 $6
+ sudo $ThisScript "$@"
if [[ $? != 0 ]] ; then
echo "This script must be run as root (or using sudo). Exiting!"
exit 1
@@ -626,7 +688,7 @@ if [[ `whoami` != "root" ]] ; then
fi
CheckForFiles
if [[ $OSName == 'Darwin' ]] ; then
- if [[ $ShimDir != "none" ]] ; then
+ if [[ $ShimSource != "none" ]] ; then
echo "The --shim option is not supported on OS X! Exiting!"
exit 1
fi
diff --git a/keys/README.txt b/keys/README.txt
new file mode 100644
index 0000000..5376570
--- /dev/null
+++ b/keys/README.txt
@@ -0,0 +1,26 @@
+This directory contains known public keys for Linux distributions and other
+parties that sign boot loaders and kernels that should be verifiable by
+shim. I'm providing these keys as a convenience to enable easy installation
+of keys should you replace your distribution's version of shim with another
+one and therefore require adding its public key as a machine owner key
+(MOK).
+
+Files come with three extensions. A filename ending in .crt is a
+certificate file that can be used by sbverify to verify the authenticity of
+a key, as in:
+
+$ sbverify --cert keys/refind.crt refind/refind_x64.efi
+
+The .cer and .der filename extensions are equivalent, and are public key
+files similar to .crt files, but in a different form. The MokManager
+utility expects its input public keys in this form, so these are the files
+you would use to add a key to the MOK list maintained by MokManager and
+used by shim.
+
+The files in this directory are:
+
+- canonical-uefi-ca.der -- Canonical's public key, used to sign Ubuntu
+ boot loaders and kernels.
+
+- refind.cer & refind.crt -- My own (Roderick W. Smith's) public key,
+ used to sign refind_x64.efi and the 64-bit rEFInd drivers.
diff --git a/keys/canonical-uefi-ca.der b/keys/canonical-uefi-ca.der
new file mode 100644
index 0000000..b4098d9
Binary files /dev/null and b/keys/canonical-uefi-ca.der differ
diff --git a/keys/refind.cer b/keys/refind.cer
new file mode 100644
index 0000000..9774f80
Binary files /dev/null and b/keys/refind.cer differ
diff --git a/keys/refind.crt b/keys/refind.crt
new file mode 100644
index 0000000..614f6d2
--- /dev/null
+++ b/keys/refind.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDOzCCAiOgAwIBAgIJAODF7HQMFVJOMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNV
+BAMMKVJvZGVyaWNrIFcuIFNtaXRoLCByb2RzbWl0aEByb2RzYm9va3MuY29tMB4X
+DTEyMTIwNjIxMzgyOFoXDTMyMTIwMTIxMzgyOFowNDEyMDAGA1UEAwwpUm9kZXJp
+Y2sgVy4gU21pdGgsIHJvZHNtaXRoQHJvZHNib29rcy5jb20wggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCqTnWTvfemH1XP4RqiCITm1Zuvwil1+XhccYx2
+YQ23IU/e1Dvdn5xtk6Qk0IQa8pYG8DrQdOQJkItv3PDYuOu0Zx/dHVm93okHBAS1
+X2JJcslswHv/hAATs0Xnv3fJt30mJ0ja+KDbSOZ3V0MH+pjBkc/6Pk7xHuOkWwjJ
+6iP5nePeD8oGvQcGuwZe9XhiK1NKa23j9WzVU8hl0buhyatBd/xASs9JnUsmEhsG
+dqasdmWp6QqTvj/QwWoJd7J5zmU0k5SGt5I0kKQGKo/epCU9XdAf5z198J0D6XyP
+fN3y2ZYTPGb/1rMNdceQXDxhl/ps3n4A/qIKiZW3Ks8cOj+HAgMBAAGjUDBOMB0G
+A1UdDgQWBBTTDAa9OVimbJh1fwmoCFXhdEpacDAfBgNVHSMEGDAWgBTTDAa9OVim
+bJh1fwmoCFXhdEpacDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCo
+9/vhRiG9oMEaJtihy4/pYTs9EiKCQ6ewzcbQaBz7mPXec7h5E4LuxhE7Rl/+1/xq
+39X8D7C0mbDyN0Drt3Ovf+hhzWdpkDIQ/7P6SdRTxAXE+/xUOj57jENPXZWV0jDt
+Uy1MGZN9IKAUXfnPfmv72FYN9XoUVv3d5yy9wSCc/9AlGHx8lGDJ/p7DJSXGmBKO
+BQV/1Y39GCxaSWdyrcjnV1swUBLO9tesfCRwfoo/rNh+wgK9P+emLbh+jSTL/zW/
+Ye1NS0VXD3pWTswA7M7XYOy6KON2vKupFyHhDj3NMzspq8/oDQHLvUzq1I8z99sd
+it92eWJ2JKoH6nSKDKXq
+-----END CERTIFICATE-----
diff --git a/libeg/libeg.h b/libeg/libeg.h
index 89ddb74..e993ee1 100644
--- a/libeg/libeg.h
+++ b/libeg/libeg.h
@@ -123,7 +123,8 @@ VOID egDrawImageArea(IN EG_IMAGE *Image,
IN UINTN ScreenPosX, IN UINTN ScreenPosY);
VOID egDisplayMessage(IN CHAR16 *Text, EG_PIXEL *BGColor);
VOID egScreenShot(VOID);
-
+//UINT32 egGetGraphicsMode(VOID);
+UINT32 egSetTextMode(UINT32 RequestedMode);
#endif /* __LIBEG_LIBEG_H__ */
diff --git a/libeg/libegint.h b/libeg/libegint.h
index 8c7f1e1..400a65c 100644
--- a/libeg/libegint.h
+++ b/libeg/libegint.h
@@ -52,7 +52,7 @@ typedef EG_IMAGE * (*EG_DECODE_FUNC)(IN UINT8 *FileData, IN UINTN FileDataLength
/* functions */
-BOOLEAN egSetScreenSize(IN UINTN ScreenWidth, IN UINTN ScreenHeight);
+BOOLEAN egSetScreenSize(IN OUT UINTN *ScreenWidth, IN OUT UINTN *ScreenHeight);
VOID egRestrictImageArea(IN EG_IMAGE *Image,
IN UINTN AreaPosX, IN UINTN AreaPosY,
diff --git a/libeg/screen.c b/libeg/screen.c
index b332704..e4f585a 100644
--- a/libeg/screen.c
+++ b/libeg/screen.c
@@ -33,9 +33,18 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
#include "libegint.h"
#include "../refind/screen.h"
+#include "../refind/lib.h"
#include "../include/refit_call_wrapper.h"
#include
@@ -100,63 +109,93 @@ VOID egInitScreen(VOID)
}
}
-// Sets the screen resolution to the specified value, if possible.
-// If the specified value is not valid, displays a warning with the valid
-// modes on UEFI systems, or silently fails on EFI 1.x systems. Note that
-// this function attempts to set ANY screen resolution, even 0x0 or
-// ridiculously large values.
+// Sets the screen resolution to the specified value, if possible. If *ScreenHeight
+// is 0 and GOP mode is detected, assume that *ScreenWidth contains a GOP mode
+// number rather than a horizontal resolution. If the specified resolution is not
+// valid, displays a warning with the valid modes on GOP (UEFI) systems, or silently
+// fails on UGA (EFI 1.x) systems. Note that this function attempts to set ANY screen
+// resolution, even 0x0 or ridiculously large values.
+// Upon success, returns actual screen resolution in *ScreenWidth and *ScreenHeight.
+// These values are unchanged upon failure.
// Returns TRUE if successful, FALSE if not.
-BOOLEAN egSetScreenSize(IN UINTN ScreenWidth, IN UINTN ScreenHeight) {
- EFI_STATUS Status = EFI_SUCCESS;
- EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
- UINT32 ModeNum = 0;
- UINTN Size;
- BOOLEAN ModeSet = FALSE;
- UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate;
+BOOLEAN egSetScreenSize(IN OUT UINTN *ScreenWidth, IN OUT UINTN *ScreenHeight) {
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ UINT32 ModeNum = 0;
+ UINTN Size;
+ BOOLEAN ModeSet = FALSE;
+ UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate;
if (GraphicsOutput != NULL) { // GOP mode (UEFI)
- // Do a loop through the modes to see if the specified one is available;
- // and if so, switch to it....
- while ((Status == EFI_SUCCESS) && (!ModeSet)) {
- Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info);
- if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info)) &&
- (Info->HorizontalResolution == ScreenWidth) && (Info->VerticalResolution == ScreenHeight)) {
- Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum);
- ModeSet = (Status == EFI_SUCCESS);
- } // if
- ModeNum++;
- } // while()
+ if (*ScreenHeight == 0) { // User specified a mode number (stored in *ScreenWidth); use it directly
+ if (*ScreenWidth == GraphicsOutput->Mode->Mode) { // user requested current mode; do nothing
+ ModeSet = TRUE;
+ *ScreenWidth = Info->HorizontalResolution;
+ *ScreenHeight = Info->VerticalResolution;
+ } else {
+ ModeNum = (UINT32) *ScreenWidth;
+ Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info);
+ if (Status == EFI_SUCCESS) {
+ Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum);
+ if (Status == EFI_SUCCESS) {
+ ModeSet = TRUE;
+ *ScreenWidth = Info->HorizontalResolution;
+ *ScreenHeight = Info->VerticalResolution;
+ } // if set mode OK
+ } // if queried mode OK
+ } // if/else
+
+ // User specified width & height; must find mode -- but only if change is required....
+ } else {
+ Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, GraphicsOutput->Mode->Mode, &Size, &Info);
+ if ((Status == EFI_SUCCESS) && (Info->HorizontalResolution == *ScreenWidth) &&
+ (Info->VerticalResolution == *ScreenHeight)) {
+ ModeSet = TRUE; // user requested current mode; do nothing
+ } else {
+ // Do a loop through the modes to see if the specified one is available;
+ // and if so, switch to it....
+ do {
+ Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info);
+ if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info)) &&
+ (Info->HorizontalResolution == *ScreenWidth) && (Info->VerticalResolution == *ScreenHeight)) {
+ Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum);
+ ModeSet = (Status == EFI_SUCCESS);
+ } // if
+ } while ((++ModeNum < GraphicsOutput->Mode->MaxMode) && !ModeSet);
+ } // if/else
+ } // if/else
if (ModeSet) {
- egScreenWidth = ScreenWidth;
- egScreenHeight = ScreenHeight;
+ egScreenWidth = *ScreenWidth;
+ egScreenHeight = *ScreenHeight;
} else {// If unsuccessful, display an error message for the user....
- Print(L"Error setting mode %d x %d; using default mode!\nAvailable modes are:\n", ScreenWidth, ScreenHeight);
+ SwitchToText(FALSE);
+ Print(L"Error setting graphics mode %d x %d; using default mode!\nAvailable modes are:\n", *ScreenWidth, *ScreenHeight);
ModeNum = 0;
- Status = EFI_SUCCESS;
- while (Status == EFI_SUCCESS) {
+ do {
Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info);
- if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info))) {
+ if ((Status == EFI_SUCCESS) && (Info != NULL)) {
Print(L"Mode %d: %d x %d\n", ModeNum, Info->HorizontalResolution, Info->VerticalResolution);
} // else
- ModeNum++;
- } // while()
+ } while (++ModeNum < GraphicsOutput->Mode->MaxMode);
PauseForKey();
+ SwitchToGraphics();
} // if()
+
} else if (UgaDraw != NULL) { // UGA mode (EFI 1.x)
// Try to use current color depth & refresh rate for new mode. Maybe not the best choice
// in all cases, but I don't know how to probe for alternatives....
Status = refit_call5_wrapper(UgaDraw->GetMode, UgaDraw, &UGAWidth, &UGAHeight, &UGADepth, &UGARefreshRate);
- Status = refit_call5_wrapper(UgaDraw->SetMode, UgaDraw, ScreenWidth, ScreenHeight, UGADepth, UGARefreshRate);
+ Status = refit_call5_wrapper(UgaDraw->SetMode, UgaDraw, *ScreenWidth, *ScreenHeight, UGADepth, UGARefreshRate);
if (Status == EFI_SUCCESS) {
- egScreenWidth = ScreenWidth;
- egScreenHeight = ScreenHeight;
+ egScreenWidth = *ScreenWidth;
+ egScreenHeight = *ScreenHeight;
ModeSet = TRUE;
} else {
// TODO: Find a list of supported modes and display it.
// NOTE: Below doesn't actually appear unless we explicitly switch to text mode.
// This is just a placeholder until something better can be done....
- Print(L"Error setting mode %d x %d; unsupported mode!\n");
+ Print(L"Error setting graphics mode %d x %d; unsupported mode!\n");
} // if/else
} // if/else if
return (ModeSet);
@@ -170,25 +209,63 @@ VOID egGetScreenSize(OUT UINTN *ScreenWidth, OUT UINTN *ScreenHeight)
*ScreenHeight = egScreenHeight;
}
+// Set a text mode
+// Returns the mode that was actually set.
+UINT32 egSetTextMode(UINT32 RequestedMode) {
+ UINTN i = 0, Width, Height;
+ UINT32 UsedMode = ST->ConOut->Mode->Mode;
+ EFI_STATUS Status;
+
+ if (RequestedMode != ST->ConOut->Mode->Mode) {
+ SwitchToGraphics();
+ Status = refit_call2_wrapper(ST->ConOut->SetMode, ST->ConOut, RequestedMode);
+ if (Status == EFI_SUCCESS) {
+ UsedMode = RequestedMode;
+ } else {
+ SwitchToText(FALSE);
+ Print(L"Error setting text mode %d; available modes are:\n", RequestedMode);
+ do {
+ Status = refit_call4_wrapper(ST->ConOut->QueryMode, ST->ConOut, i, &Width, &Height);
+ if (Status == EFI_SUCCESS)
+ Print(L"Mode %d: %d x %d\n", i, Width, Height);
+ } while (++i < ST->ConOut->Mode->MaxMode);
+
+ PauseForKey();
+ SwitchToGraphics();
+ } // if/else successful change
+ } // if need to change mode
+ return UsedMode;
+} // UINT32 egSetTextMode()
+
CHAR16 * egScreenDescription(VOID)
{
- CHAR16 *Temp;
+ CHAR16 *GraphicsInfo, *TextInfo = NULL;
+
+ GraphicsInfo = AllocateZeroPool(256 * sizeof(CHAR16));
+ if (GraphicsInfo == NULL)
+ return L"memory allocation error";
if (egHasGraphics) {
if (GraphicsOutput != NULL) {
- Temp = AllocateZeroPool(256 * sizeof(CHAR16));
- SPrint(Temp, 255, L"Graphics Output (UEFI), %dx%d", egScreenWidth, egScreenHeight);
- return Temp;
+ SPrint(GraphicsInfo, 255, L"Graphics Output (UEFI), %dx%d", egScreenWidth, egScreenHeight);
} else if (UgaDraw != NULL) {
- Temp = AllocateZeroPool(256 * sizeof(CHAR16));
- SPrint(Temp, 255, L"UGA Draw (EFI 1.10), %dx%d", egScreenWidth, egScreenHeight);
- return Temp;
+ GraphicsInfo = AllocateZeroPool(256 * sizeof(CHAR16));
+ SPrint(GraphicsInfo, 255, L"UGA Draw (EFI 1.10), %dx%d", egScreenWidth, egScreenHeight);
} else {
+ MyFreePool(GraphicsInfo);
+ MyFreePool(TextInfo);
return L"Internal Error";
}
+ if (!AllowGraphicsMode) { // graphics-capable HW, but in text mode
+ TextInfo = AllocateZeroPool(256 * sizeof(CHAR16));
+ SPrint(TextInfo, 255, L"(in %dx%d text mode)", ConWidth, ConHeight);
+ MergeStrings(&GraphicsInfo, TextInfo, L' ');
+ }
} else {
- return L"Text Console";
+ SPrint(GraphicsInfo, 255, L"Text-foo console, %dx%d", ConWidth, ConHeight);
}
+ MyFreePool(TextInfo);
+ return GraphicsInfo;
}
BOOLEAN egHasGraphicsMode(VOID)
@@ -234,9 +311,15 @@ VOID egClearScreen(IN EG_PIXEL *Color)
if (!egHasGraphics)
return;
- FillColor.Red = Color->r;
- FillColor.Green = Color->g;
- FillColor.Blue = Color->b;
+ if (Color != NULL) {
+ FillColor.Red = Color->r;
+ FillColor.Green = Color->g;
+ FillColor.Blue = Color->b;
+ } else {
+ FillColor.Red = 0x0;
+ FillColor.Green = 0x0;
+ FillColor.Blue = 0x0;
+ }
FillColor.Reserved = 0;
if (GraphicsOutput != NULL) {
@@ -244,10 +327,9 @@ VOID egClearScreen(IN EG_PIXEL *Color)
// layout, and the header from TianoCore actually defines them
// to be the same type.
refit_call10_wrapper(GraphicsOutput->Blt, GraphicsOutput, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)&FillColor, EfiBltVideoFill,
- 0, 0, 0, 0, egScreenWidth, egScreenHeight, 0);
+ 0, 0, 0, 0, egScreenWidth, egScreenHeight, 0);
} else if (UgaDraw != NULL) {
- refit_call10_wrapper(UgaDraw->Blt, UgaDraw, &FillColor, EfiUgaVideoFill,
- 0, 0, 0, 0, egScreenWidth, egScreenHeight, 0);
+ refit_call10_wrapper(UgaDraw->Blt, UgaDraw, &FillColor, EfiUgaVideoFill, 0, 0, 0, 0, egScreenWidth, egScreenHeight, 0);
}
}
diff --git a/libeg/text.c b/libeg/text.c
index d84eeb7..93551b2 100644
--- a/libeg/text.c
+++ b/libeg/text.c
@@ -64,7 +64,11 @@ VOID egRenderText(IN CHAR16 *Text, IN OUT EG_IMAGE *CompImage, IN UINTN PosX, IN
UINTN i, c;
// clip the text
- TextLength = StrLen(Text);
+ if (Text)
+ TextLength = StrLen(Text);
+ else
+ TextLength = 0;
+
if (TextLength * FONT_CELL_WIDTH + PosX > CompImage->Width)
TextLength = (CompImage->Width - PosX) / FONT_CELL_WIDTH;
diff --git a/mkdistrib b/mkdistrib
index e55521b..78f24e3 100755
--- a/mkdistrib
+++ b/mkdistrib
@@ -5,7 +5,7 @@
# Updated 11/8/2012 to do more things automatically
# Updated 12/6/2012 to sign binaries with the rEFInd MOK
#
-# Usage: ./mkdistrib version
+# Usage: ./mkdistrib version [--nosign]
# where "version" is a version number
# MUST be run from an x86-64 system, on which the TianoCore build
# includes both X64 and IA32 build support ("TARGET_ARCH = IA32 X64"
@@ -13,25 +13,30 @@
# partition to be mounted via /etc/fstab at /mnt/refind.
+if [[ $2 == "--nosign" ]] ; then
+ SignIt=0
+else
+ SignIt=1
+fi
+
StartDir=`pwd`
SBSign=`which sbsign 2> /dev/null`
KeysDir=/mnt/refind
KeysInfo=`df $KeysDir 2> /dev/null | grep $KeysDir`
-if [[ ! -n $SBSign ]] ; then
+if [[ ! -n $SBSign && $SignIt == 1 ]] ; then
echo "Can't find sbsign binary! Aborting!"
exit 1
fi
-if [[ ! -n $KeysInfo ]] ; then
+if [[ ! -n $KeysInfo && $SignIt == 1 ]] ; then
mount /mnt/refind
-fi
-
-if [[ $? -ne 0 ]] ; then
- echo "Error mounting $KeysDir! Aborting!"
- echo ""
- exit 1
+ if [[ $? -ne 0 ]] ; then
+ echo "Error mounting $KeysDir! Aborting!"
+ echo ""
+ exit 1
+ fi
fi
# From here on, if there's an error, abort immediately.
@@ -42,8 +47,7 @@ make clean
# Prepare a place and copy files there....
mkdir -p ../snapshots/$1/refind-$1/icons
cp --preserve=timestamps icons/*icns ../snapshots/$1/refind-$1/icons/
-cp -a docs images include EfiLib libeg refind filesystems install.sh CREDITS.txt NEWS.txt BUILDING.txt COPYING.txt LICENSE.txt README.txt refind.inf Make.tiano Make.common Makefile refind.conf-sample ../snapshots/$1/refind-$1
-cp $KeysDir/refind.cer $KeysDir/refind.crt ../snapshots/$1/refind-$1/
+cp -a docs images keys include EfiLib libeg refind filesystems install.sh mkrlconf.sh CREDITS.txt NEWS.txt BUILDING.txt COPYING.txt LICENSE.txt README.txt refind.inf Make.tiano Make.common Makefile refind.conf-sample ../snapshots/$1/refind-$1
# Go there and prepare a souce code zip file....
cd ../snapshots/$1/
@@ -65,19 +69,28 @@ make
make fs
mkdir -p refind-bin-$1/refind/drivers_x64
cp -a icons refind-bin-$1/refind/
-for File in `ls drivers_x64/*_x64.efi` ; do
- $SBSign --key $KeysDir/refind.key --cert $KeysDir/refind.crt --output refind-bin-$1/refind/$File $File
-done
+if [[ $SignIt == 1 ]] ; then
+ for File in `ls drivers_x64/*_x64.efi` ; do
+ $SBSign --key $KeysDir/refind.key --cert $KeysDir/refind.crt --output refind-bin-$1/refind/$File $File
+ done
+else
+ cp --preserve=timestamps drivers_x64/*_x64.efi refind-bin-$1/refind/drivers_x64/
+fi
cp --preserve=timestamps filesystems/LICENSE*txt refind-bin-$1/refind/drivers_x64/
cp --preserve=timestamps refind.conf-sample refind-bin-$1/refind/
-$SBSign --key $KeysDir/refind.key --cert $KeysDir/refind.crt --output refind-bin-$1/refind/refind_x64.efi refind/refind_x64.efi
+if [[ $SignIt == 1 ]] ; then
+ $SBSign --key $KeysDir/refind.key --cert $KeysDir/refind.crt --output refind-bin-$1/refind/refind_x64.efi refind/refind_x64.efi
+else
+ cp refind/refind_x64.efi refind-bin-$1/refind/refind_x64.efi
+fi
cp refind-bin-$1/refind/refind_x64.efi $StartDir
-cp -a COPYING.txt LICENSE.txt README.txt docs CREDITS.txt install.sh refind-bin-$1
+cp -a docs keys COPYING.txt LICENSE.txt README.txt CREDITS.txt install.sh mkrlconf.sh refind-bin-$1
# Prepare the final .zip file and clean up
-cp $KeysDir/refind.cer $KeysDir/refind.crt refind-bin-$1/
+if [[ $SignIt == 1 ]] ; then
+ umount $KeysDir
+fi
zip -9r ../refind-bin-$1.zip refind-bin-$1
cd ..
rm -r refind-$1
cd $StartDir
-umount $KeysDir
\ No newline at end of file
diff --git a/mkrlconf.sh b/mkrlconf.sh
new file mode 100755
index 0000000..c12ee8a
--- /dev/null
+++ b/mkrlconf.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# Script to create a refind_linux.conf file for the current Linux
+# installation.
+
+# copyright (c) 2012 by Roderick W. Smith
+#
+# This program is licensed under the terms of the GNU GPL, version 3,
+# a copy of which should be distributed with this program.
+
+# Usage:
+#
+# ./mkrlconf.sh [--overwrite]
+#
+# Options:
+#
+# --force -- Overwrite an existing file (default is to not replace existing file)
+
+# Revision history:
+#
+# 0.5.1 -- Initial release
+#
+# Note: mkrlconf.sh version numbers match those of the rEFInd package
+# with which they first appeared.
+
+RLConfFile="/boot/refind_linux.conf"
+
+if [[ ! -f $RLConfFile || $1 == "--force" ]] ; then
+ if [[ -f /etc/default/grub ]] ; then
+ # We want the default options used by the distribution, stored here....
+ source /etc/default/grub
+ fi
+ RootFS=`df / | grep dev | cut -f 1 -d " "`
+ StartOfDevname=`echo $RootFS | cut -b 1-7`
+ if [[ $StartOfDevname == "/dev/sd" || $StartOfDevName == "/dev/hd" ]] ; then
+ # Identify root filesystem by UUID rather than by device node, if possible
+ Uuid=`blkid -o export $RootFS 2> /dev/null | grep UUID=`
+ if [[ -n $Uuid ]] ; then
+ RootFS=$Uuid
+ fi
+ fi
+ DefaultOptions="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
+ echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
+ echo "\"Boot to single-user mode\" \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
+ echo "\"Boot with minimal options\" \"ro root=$RootFS\"" >> $RLConfFile
+else
+ echo "Existing $RLConfFile found! Not overwriting!"
+ echo "To force overwriting, pass the --force option."
+ echo ""
+fi
diff --git a/refind.conf-sample b/refind.conf-sample
index 42c73fc..7d77fde 100644
--- a/refind.conf-sample
+++ b/refind.conf-sample
@@ -11,12 +11,15 @@ timeout 20
# Hide user interface elements for personal preference or to increase
# security:
# banner - the rEFInd title banner
-# label - text label in the menu
+# label - boot option text label in the menu
# singleuser - remove the submenu options to boot Mac OS X in single-user
# or verbose modes; affects ONLY MacOS X
# hwtest - the submenu option to run Apple's hardware test
# arrows - scroll arrows on the OS selection tag line
+# hints - brief command summary in the menu
+# editor - the options editor (+, F2, or Insert on boot options menu)
# all - all of the above
+# Default is none of these (all elements active)
#
#hideui singleuser
#hideui all
@@ -52,20 +55,38 @@ timeout 20
#selection_small selection-small.bmp
# Use text mode only. When enabled, this option forces rEFInd into text mode.
+# Passing this option a "0" value causes graphics mode to be used. Pasing
+# it no value or any non-0 value causes text mode to be used.
+# Default is to use graphics mode.
#
#textonly
-# Set the screen's video resolution. Pass this option two values,
-# corresponding to the X and Y resolutions. Note that not all resolutions
-# are supported. On UEFI systems, passing an incorrect value results in a
-# message being shown on the screen to that effect, along with a list of
-# supported modes. On EFI 1.x systems (e.g., Macintoshes), setting an
-# incorrect mode silently fails. On both types of systems, setting an
-# incorrect resolution results in the default resolution being used.
-# A resolution of 1024x768 usually works, but higher values often don't.
+# Set the EFI text mode to be used for textual displays. This option
+# takes a single digit that refers to a mode number. The default is 0
+# (80x25), 1 is sometimes 80x50, and higher numbers are system-specific
+# modes. If you specify an invalid mode, rEFInd pauses during boot to
+# inform you of valid modes.
+# CAUTION: On VirtualBox, and perhaps on some real computers, specifying
+# a text mode and uncommenting the "textonly" option while NOT specifying
+# a resolution can result in an unusable display in the booted OS.
+# Default is 0
+#
+#textmode 2
+
+# Set the screen's video resolution. Pass this option either:
+# * two values, corresponding to the X and Y resolutions
+# * one value, corresponding to a GOP (UEFI) video mode
+# Note that not all resolutions are supported. On UEFI systems, passing
+# an incorrect value results in a message being shown on the screen to
+# that effect, along with a list of supported modes. On EFI 1.x systems
+# (e.g., Macintoshes), setting an incorrect mode silently fails. On both
+# types of systems, setting an incorrect resolution results in the default
+# resolution being used. A resolution of 1024x768 usually works, but higher
+# values often don't.
# Default is "0 0" (use the system default resolution, usually 800x600).
#
#resolution 1024 768
+#resolution 3
# Launch specified OSes in graphics mode. By default, rEFInd switches
# to text mode and displays basic pre-launch information when launching
@@ -146,10 +167,19 @@ timeout 20
# Directories are specified relative to the volume's root directory. This
# option applies to ALL the volumes that rEFInd scans. If a specified
# directory doesn't exist, it's ignored (no error condition results).
-# The default is to scan no additional directories.
+# The default is to scan the "boot" directory in addition to various
+# hard-coded directories.
#
#also_scan_dirs boot,EFI/linux/kernels
+# Partitions to omit from scans. You must specify a volume by its
+# label, which you can obtain in an EFI shell by typing "vol", from
+# Linux by typing "blkid /dev/{devicename}", or by examining the
+# disk's label in various OSes' file browsers.
+# The default is an empty list (all volumes are scanned).
+#
+#dont_scan_volumes
+
# Directories that should NOT be scanned for boot loaders. By default,
# rEFInd doesn't scan its own directory or the EFI/tools directory.
# You can "blacklist" additional directories with this option, which
@@ -188,6 +218,9 @@ timeout 20
# want to give a kernel a custom icon by placing an icon with the kernel's
# filename but a ".icns" extension in the same directory as the kernel, this
# option will cause the icon file to show up as a non-functional loader tag.
+# Passing this option a "0" value causes kernels without ".efi" extensions
+# to NOT be scanned; passing it alone or with any other value causes all
+# kernels to be scanned.
# Default is to NOT scan for kernels without ".efi" extensions.
#
scan_all_linux_kernels
@@ -211,6 +244,14 @@ scan_all_linux_kernels
#
#default_selection 1
+# Include a secondary configuration file within this one. This secondary
+# file is loaded as if its options appeared at the point of the "include"
+# token itself, so if you want to override a setting in the main file,
+# the secondary file must be referenced AFTER the setting you want to
+# override. Note that the secondary file may NOT load a tertiary file.
+#
+#include manual.conf
+
# Sample manual configuration stanzas. Each begins with the "menuentry"
# keyword followed by a name that's to appear in the menu (use quotes
# if you want the name to contain a space) and an open curly brace
diff --git a/refind/config.c b/refind/config.c
index e275085..b1e0929 100644
--- a/refind/config.c
+++ b/refind/config.c
@@ -53,7 +53,6 @@
// constants
-#define CONFIG_FILE_NAME L"refind.conf"
#define LINUX_OPTIONS_FILENAMES L"refind_linux.conf,refind-linux.conf"
#define MAXCONFIGFILESIZE (128*1024)
@@ -336,7 +335,7 @@ static VOID HandleStrings(IN CHAR16 **TokenList, IN UINTN TokenCount, OUT CHAR16
} // static VOID HandleStrings()
// read config file
-VOID ReadConfig(VOID)
+VOID ReadConfig(CHAR16 *FileName)
{
EFI_STATUS Status;
REFIT_FILE File;
@@ -344,20 +343,27 @@ VOID ReadConfig(VOID)
CHAR16 *FlagName;
UINTN TokenCount, i;
- if (!FileExists(SelfDir, CONFIG_FILE_NAME)) {
- Print(L"Configuration file missing!\n");
+ // 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.DontScanVolumes);
+// GlobalConfig.DontScanVolumes = StrDuplicate(L" ");
+ MyFreePool(GlobalConfig.DontScanDirs);
+ GlobalConfig.DontScanDirs = StrDuplicate(SelfDirPath);
+ MyFreePool(GlobalConfig.DontScanFiles);
+ GlobalConfig.DontScanFiles = StrDuplicate(DONT_SCAN_FILES);
+ }
+
+ if (!FileExists(SelfDir, FileName)) {
+ Print(L"Configuration file '%s' missing!\n", FileName);
return;
}
- Status = ReadFile(SelfDir, CONFIG_FILE_NAME, &File, &i);
+ Status = ReadFile(SelfDir, FileName, &File, &i);
if (EFI_ERROR(Status))
return;
- MyFreePool(GlobalConfig.DontScanDirs);
- GlobalConfig.DontScanDirs = StrDuplicate(SelfDirPath);
- MyFreePool(GlobalConfig.DontScanFiles);
- GlobalConfig.DontScanFiles = StrDuplicate(DONT_SCAN_FILES);
-
for (;;) {
TokenCount = ReadTokenLine(&File, &TokenList);
if (TokenCount == 0)
@@ -374,13 +380,17 @@ VOID ReadConfig(VOID)
} else if (StriCmp(FlagName, L"label") == 0) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_LABEL;
} else if (StriCmp(FlagName, L"singleuser") == 0) {
- GlobalConfig.HideUIFlags |= HIDEUI_FLAG_SINGLEUSER;
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_SINGLEUSER;
} else if (StriCmp(FlagName, L"hwtest") == 0) {
- GlobalConfig.HideUIFlags |= HIDEUI_FLAG_HWTEST;
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_HWTEST;
} else if (StriCmp(FlagName, L"arrows") == 0) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_ARROWS;
+ } else if (StriCmp(FlagName, L"hints") == 0) {
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_HINTS;
+ } else if (StriCmp(FlagName, L"editor") == 0) {
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_EDITOR;
} else if (StriCmp(FlagName, L"all") == 0) {
- GlobalConfig.HideUIFlags = HIDEUI_ALL;
+ GlobalConfig.HideUIFlags = HIDEUI_FLAG_ALL;
} else {
Print(L" unknown hideui flag: '%s'\n", FlagName);
}
@@ -403,6 +413,15 @@ VOID ReadConfig(VOID)
} else if (StriCmp(TokenList[0], L"also_scan_dirs") == 0) {
HandleStrings(TokenList, TokenCount, &(GlobalConfig.AlsoScan));
+ } else if ((StriCmp(TokenList[0], L"don't_scan_volumes") == 0) || (StriCmp(TokenList[0], L"dont_scan_volumes") == 0)) {
+ HandleStrings(TokenList, TokenCount, &(GlobalConfig.AlsoScan));
+ // Note: Don't use HandleStrings() because it modifies slashes, which might be present in volume name
+ MyFreePool(GlobalConfig.DontScanVolumes);
+ GlobalConfig.DontScanVolumes = NULL;
+ for (i = 1; i < TokenCount; i++) {
+ MergeStrings(&GlobalConfig.DontScanVolumes, TokenList[i], L',');
+ }
+
} else if ((StriCmp(TokenList[0], L"don't_scan_dirs") == 0) || (StriCmp(TokenList[0], L"dont_scan_dirs") == 0)) {
HandleStrings(TokenList, TokenCount, &(GlobalConfig.DontScanDirs));
@@ -450,11 +469,21 @@ VOID ReadConfig(VOID)
HandleString(TokenList, TokenCount, &(GlobalConfig.DefaultSelection));
} else if (StriCmp(TokenList[0], L"textonly") == 0) {
- GlobalConfig.TextOnly = TRUE;
+ if ((TokenCount >= 2) && (StriCmp(TokenList[1], L"0") == 0)) {
+ GlobalConfig.TextOnly = FALSE;
+ } else {
+ GlobalConfig.TextOnly = TRUE;
+ }
+
+ } else if (StriCmp(TokenList[0], L"textmode") == 0) {
+ HandleInt(TokenList, TokenCount, &(GlobalConfig.RequestedTextMode));
- } else if ((StriCmp(TokenList[0], L"resolution") == 0) && (TokenCount == 3)) {
+ } else if ((StriCmp(TokenList[0], L"resolution") == 0) && ((TokenCount == 2) || (TokenCount == 3))) {
GlobalConfig.RequestedScreenWidth = Atoi(TokenList[1]);
- GlobalConfig.RequestedScreenHeight = Atoi(TokenList[2]);
+ if (TokenCount == 3)
+ GlobalConfig.RequestedScreenHeight = Atoi(TokenList[2]);
+ else
+ GlobalConfig.RequestedScreenHeight = 0;
} else if (StriCmp(TokenList[0], L"use_graphics_for") == 0) {
GlobalConfig.GraphicsFor = 0;
@@ -473,11 +502,20 @@ VOID ReadConfig(VOID)
} // for (graphics_on tokens)
} else if (StriCmp(TokenList[0], L"scan_all_linux_kernels") == 0) {
- GlobalConfig.ScanAllLinux = TRUE;
+ if ((TokenCount >= 2) && (StriCmp(TokenList[1], L"0") == 0)) {
+ GlobalConfig.ScanAllLinux = FALSE;
+ } else {
+ GlobalConfig.ScanAllLinux = TRUE;
+ }
} else if (StriCmp(TokenList[0], L"max_tags") == 0) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.MaxTags));
+ } else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) && (StriCmp(FileName, CONFIG_FILE_NAME) == 0)) {
+ if (StriCmp(TokenList[1], FileName) != 0) {
+ ReadConfig(TokenList[1]);
+ }
+
}
FreeTokenLine(&TokenList, &TokenCount);
@@ -691,7 +729,6 @@ VOID ScanUserConfigured(VOID)
CHAR16 *Title = NULL;
UINTN TokenCount, size;
LOADER_ENTRY *Entry;
-// REFIT_MENU_SCREEN *SubScreen;
if (FileExists(SelfDir, CONFIG_FILE_NAME)) {
Status = ReadFile(SelfDir, CONFIG_FILE_NAME, &File, &size);
diff --git a/refind/config.h b/refind/config.h
index 5e5b042..bc211a9 100644
--- a/refind/config.h
+++ b/refind/config.h
@@ -67,17 +67,22 @@ typedef struct {
CHAR16 *End16Ptr;
} REFIT_FILE;
+#define HIDEUI_FLAG_NONE (0x0000)
#define HIDEUI_FLAG_BANNER (0x0001)
#define HIDEUI_FLAG_LABEL (0x0002)
#define HIDEUI_FLAG_SINGLEUSER (0x0004)
#define HIDEUI_FLAG_HWTEST (0x0008)
#define HIDEUI_FLAG_ARROWS (0x0010)
-#define HIDEUI_ALL ((0xffff))
+#define HIDEUI_FLAG_HINTS (0x0020)
+#define HIDEUI_FLAG_EDITOR (0x0040)
+#define HIDEUI_FLAG_ALL ((0xffff))
+#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(VOID);
+VOID ReadConfig(CHAR16 *FileName);
VOID ScanUserConfigured(VOID);
UINTN ReadTokenLine(IN REFIT_FILE *File, OUT CHAR16 ***TokenList);
VOID FreeTokenLine(IN OUT CHAR16 ***TokenList, IN OUT UINTN *TokenCount);
diff --git a/refind/global.h b/refind/global.h
index c993b44..511dcac 100644
--- a/refind/global.h
+++ b/refind/global.h
@@ -35,11 +35,11 @@
*/
/*
* Modifications copyright (c) 2012 Roderick W. Smith
- *
+ *
* Modifications distributed under the terms of the GNU General Public
* License (GPL) version 3 (GPLv3), a copy of which must be distributed
* with this source code or binaries made from it.
- *
+ *
*/
#ifndef __GLOBAL_H_
@@ -110,8 +110,15 @@
#define DEVICE_TYPE_BIOS 0x05 /* returned by legacy (BIOS) boot loaders */
#define DEVICE_TYPE_END 0x75 /* end of path */
-//TODO: may want to make this configurable via config file
-//static UINT16 SupportedLegacyDevices[] = {BBS_HARDDISK, BBS_CDROM, BBS_USB};
+// Filesystem type identifiers. Not all are yet used....
+#define FS_TYPE_UNKNOWN 0
+#define FS_TYPE_FAT 1
+#define FS_TYPE_EXT2 2
+#define FS_TYPE_EXT3 3
+#define FS_TYPE_EXT4 4
+#define FS_TYPE_HFSPLUS 5
+#define FS_TYPE_REISERFS 6
+#define FS_TYPE_ISO9660 7
//
// global definitions
@@ -152,6 +159,7 @@ typedef struct {
EFI_DEVICE_PATH *WholeDiskDevicePath;
MBR_PARTITION_INFO *MbrPartitionTable;
BOOLEAN IsReadable;
+ UINT32 FSType;
} REFIT_VOLUME;
typedef struct _refit_menu_entry {
@@ -174,6 +182,8 @@ typedef struct _refit_menu_screen {
REFIT_MENU_ENTRY **Entries;
UINTN TimeoutSeconds;
CHAR16 *TimeoutText;
+ CHAR16 *Hint1;
+ CHAR16 *Hint2;
} REFIT_MENU_SCREEN;
typedef struct {
@@ -204,6 +214,7 @@ typedef struct {
BOOLEAN ScanAllLinux;
UINTN RequestedScreenWidth;
UINTN RequestedScreenHeight;
+ UINTN RequestedTextMode;
UINTN Timeout;
UINTN HideUIFlags;
UINTN MaxTags; // max. number of OS entries to show simultaneously in graphics mode
@@ -215,6 +226,7 @@ typedef struct {
CHAR16 *SelectionBigFileName;
CHAR16 *DefaultSelection;
CHAR16 *AlsoScan;
+ CHAR16 *DontScanVolumes;
CHAR16 *DontScanDirs;
CHAR16 *DontScanFiles;
CHAR16 *DriverDirs;
diff --git a/refind/lib.c b/refind/lib.c
index 77e6842..958bb52 100644
--- a/refind/lib.c
+++ b/refind/lib.c
@@ -64,6 +64,15 @@ EFI_DEVICE_PATH EndDevicePath[] = {
//#define EndDevicePath DevicePath
#endif
+// "Magic" signatures for various filesystems
+#define FAT_MAGIC 0xAA55
+#define EXT2_SUPER_MAGIC 0xEF53
+#define HFSPLUS_MAGIC1 0x2B48
+#define HFSPLUS_MAGIC2 0x5848
+#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
+#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
+#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
+
// variables
EFI_HANDLE SelfImageHandle;
@@ -79,6 +88,10 @@ UINTN VolumesCount = 0;
// Maximum size for disk sectors
#define SECTOR_SIZE 4096
+// Number of bytes to read from a partition to determine its filesystem type
+// and identify its boot loader, and hence probable BIOS-mode OS installation
+#define SAMPLE_SIZE 69632 /* 68 KiB -- ReiserFS superblock begins at 64 KiB */
+
// Default names for volume badges (mini-icon to define disk type) and icons
#define VOLUME_BADGE_NAME L".VolumeBadge.icns"
#define VOLUME_ICON_NAME L".VolumeIcon.icns"
@@ -94,7 +107,7 @@ static VOID UninitVolumes(VOID);
//
// Converts forward slashes to backslashes, removes duplicate slashes, and
-// removes slashes from the end of the pathname.
+// removes slashes from both the start and end of the pathname.
// Necessary because some (buggy?) EFI implementations produce "\/" strings
// in pathnames, because some user inputs can produce duplicate directory
// separators, and because we want consistent start and end slashes for
@@ -106,23 +119,20 @@ VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) {
UINTN i, FinalChar = 0;
BOOLEAN LastWasSlash = FALSE;
- NewName = AllocateZeroPool(sizeof(CHAR16) * (StrLen(PathName) + 4));
+ NewName = AllocateZeroPool(sizeof(CHAR16) * (StrLen(PathName) + 2));
if (NewName != NULL) {
for (i = 0; i < StrLen(PathName); i++) {
if ((PathName[i] == L'/') || (PathName[i] == L'\\')) {
- if ((!LastWasSlash) /* && (FinalChar != 0) */)
+ if ((!LastWasSlash) && (FinalChar != 0))
NewName[FinalChar++] = L'\\';
LastWasSlash = TRUE;
} else {
- if (FinalChar == 0) {
- NewName[FinalChar++] = L'\\';
- }
NewName[FinalChar++] = PathName[i];
LastWasSlash = FALSE;
} // if/else
} // for
NewName[FinalChar] = 0;
- if ((FinalChar > 1) && (NewName[FinalChar - 1] == L'\\'))
+ if ((FinalChar > 0) && (NewName[FinalChar - 1] == L'\\'))
NewName[--FinalChar] = 0;
if (FinalChar == 0) {
NewName[0] = L'\\';
@@ -372,10 +382,97 @@ VOID ExtractLegacyLoaderPaths(EFI_DEVICE_PATH **PathList, UINTN MaxPaths, EFI_DE
// volume functions
//
-static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootable)
+// Return a pointer to a string containing a filesystem type name. If the
+// filesystem type is unknown, a blank (but non-null) string is returned.
+// The returned variable is a constant that should NOT be freed.
+static CHAR16 *FSTypeName(IN UINT32 TypeCode) {
+ CHAR16 *retval = NULL;
+
+ switch (TypeCode) {
+ case FS_TYPE_FAT:
+ retval = L" FAT";
+ break;
+ case FS_TYPE_HFSPLUS:
+ retval = L" HFS+";
+ break;
+ case FS_TYPE_EXT2:
+ retval = L" ext2";
+ break;
+ case FS_TYPE_EXT3:
+ retval = L" ext3";
+ break;
+ case FS_TYPE_EXT4:
+ retval = L" ext4";
+ break;
+ case FS_TYPE_REISERFS:
+ retval = L" ReiserFS";
+ break;
+ case FS_TYPE_ISO9660:
+ retval = L" ISO-9660";
+ break;
+ default:
+ retval = L"";
+ break;
+ } // switch
+ return retval;
+} // CHAR16 *FSTypeName()
+
+// Identify the filesystem type, if possible. Expects a Buffer containing
+// the first few (normally 4096) bytes of the filesystem, and outputs a
+// code representing the identified filesystem type.
+static UINT32 IdentifyFilesystemType(IN UINT8 *Buffer, IN UINTN BufferSize) {
+ UINT32 FoundType = FS_TYPE_UNKNOWN;
+ UINT32 *Ext2Incompat, *Ext2Compat;
+ UINT16 *Magic16;
+ char *MagicString;
+
+ if (Buffer != NULL) {
+
+ if (BufferSize >= 512) {
+ Magic16 = (UINT16*) (Buffer + 510);
+ if (*Magic16 == FAT_MAGIC)
+ return FS_TYPE_FAT;
+ } // search for FAT magic
+
+ if (BufferSize >= (1024 + 100)) {
+ Magic16 = (UINT16*) (Buffer + 1024 + 56);
+ if (*Magic16 == EXT2_SUPER_MAGIC) { // ext2/3/4
+ Ext2Compat = (UINT32*) (Buffer + 1024 + 92);
+ Ext2Incompat = (UINT32*) (Buffer + 1024 + 96);
+ if ((*Ext2Incompat & 0x0040) || (*Ext2Incompat & 0x0200)) { // check for extents or flex_bg
+ return FS_TYPE_EXT4;
+ } else if (*Ext2Compat & 0x0004) { // check for journal
+ return FS_TYPE_EXT3;
+ } else { // none of these features; presume it's ext2...
+ return FS_TYPE_EXT2;
+ }
+ }
+ } // search for ext2/3/4 magic
+
+ if (BufferSize >= (65536 + 62)) {
+ MagicString = (char*) (Buffer + 65536 + 52);
+ if ((CompareMem(MagicString, REISERFS_SUPER_MAGIC_STRING, 8) == 0) ||
+ (CompareMem(MagicString, REISER2FS_SUPER_MAGIC_STRING, 9) == 0) ||
+ (CompareMem(MagicString, REISER2FS_JR_SUPER_MAGIC_STRING, 9) == 0)) {
+ return FS_TYPE_REISERFS;
+ } // if
+ } // search for ReiserFS magic
+
+ if (BufferSize >= (1024 + 2)) {
+ Magic16 = (UINT16*) (Buffer + 1024);
+ if ((*Magic16 == HFSPLUS_MAGIC1) || (*Magic16 == HFSPLUS_MAGIC2)) {
+ return FS_TYPE_HFSPLUS;
+ }
+ } // search for HFS+ magic
+ } // if (Buffer != NULL)
+
+ return FoundType;
+}
+
+static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
{
EFI_STATUS Status;
- UINT8 SectorBuffer[SECTOR_SIZE];
+ UINT8 Buffer[SAMPLE_SIZE];
UINTN i;
MBR_PARTITION_INFO *MbrTable;
BOOLEAN MbrTableFound;
@@ -387,97 +484,98 @@ static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootabl
if (Volume->BlockIO == NULL)
return;
- if (Volume->BlockIO->Media->BlockSize > SECTOR_SIZE)
+ if (Volume->BlockIO->Media->BlockSize > SAMPLE_SIZE)
return; // our buffer is too small...
// look at the boot sector (this is used for both hard disks and El Torito images!)
Status = refit_call5_wrapper(Volume->BlockIO->ReadBlocks,
Volume->BlockIO, Volume->BlockIO->Media->MediaId,
- Volume->BlockIOOffset, SECTOR_SIZE, SectorBuffer);
+ Volume->BlockIOOffset, SAMPLE_SIZE, Buffer);
if (!EFI_ERROR(Status)) {
- if (*((UINT16 *)(SectorBuffer + 510)) == 0xaa55 && SectorBuffer[0] != 0) {
+ Volume->FSType = IdentifyFilesystemType(Buffer, SAMPLE_SIZE);
+ if (*((UINT16 *)(Buffer + 510)) == 0xaa55 && Buffer[0] != 0) {
*Bootable = TRUE;
Volume->HasBootCode = TRUE;
}
// detect specific boot codes
- if (CompareMem(SectorBuffer + 2, "LILO", 4) == 0 ||
- CompareMem(SectorBuffer + 6, "LILO", 4) == 0 ||
- CompareMem(SectorBuffer + 3, "SYSLINUX", 8) == 0 ||
- FindMem(SectorBuffer, SECTOR_SIZE, "ISOLINUX", 8) >= 0) {
+ if (CompareMem(Buffer + 2, "LILO", 4) == 0 ||
+ CompareMem(Buffer + 6, "LILO", 4) == 0 ||
+ CompareMem(Buffer + 3, "SYSLINUX", 8) == 0 ||
+ FindMem(Buffer, SECTOR_SIZE, "ISOLINUX", 8) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"linux";
Volume->OSName = L"Linux";
- } else if (FindMem(SectorBuffer, 512, "Geom\0Hard Disk\0Read\0 Error", 26) >= 0) { // GRUB
+ } else if (FindMem(Buffer, 512, "Geom\0Hard Disk\0Read\0 Error", 26) >= 0) { // GRUB
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"grub,linux";
Volume->OSName = L"Linux";
// // Below doesn't produce a bootable entry, so commented out for the moment....
// // GRUB in BIOS boot partition:
-// } else if (FindMem(SectorBuffer, 512, "Geom\0Read\0 Error", 16) >= 0) {
+// } else if (FindMem(Buffer, 512, "Geom\0Read\0 Error", 16) >= 0) {
// Volume->HasBootCode = TRUE;
// Volume->OSIconName = L"grub,linux";
// Volume->OSName = L"Linux";
// Volume->VolName = L"BIOS Boot Partition";
// *Bootable = TRUE;
- } else if ((*((UINT32 *)(SectorBuffer + 502)) == 0 &&
- *((UINT32 *)(SectorBuffer + 506)) == 50000 &&
- *((UINT16 *)(SectorBuffer + 510)) == 0xaa55) ||
- FindMem(SectorBuffer, SECTOR_SIZE, "Starting the BTX loader", 23) >= 0) {
+ } else if ((*((UINT32 *)(Buffer + 502)) == 0 &&
+ *((UINT32 *)(Buffer + 506)) == 50000 &&
+ *((UINT16 *)(Buffer + 510)) == 0xaa55) ||
+ FindMem(Buffer, SECTOR_SIZE, "Starting the BTX loader", 23) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"freebsd";
Volume->OSName = L"FreeBSD";
- } else if (FindMem(SectorBuffer, 512, "!Loading", 8) >= 0 ||
- FindMem(SectorBuffer, SECTOR_SIZE, "/cdboot\0/CDBOOT\0", 16) >= 0) {
+ } else if (FindMem(Buffer, 512, "!Loading", 8) >= 0 ||
+ FindMem(Buffer, SECTOR_SIZE, "/cdboot\0/CDBOOT\0", 16) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"openbsd";
Volume->OSName = L"OpenBSD";
- } else if (FindMem(SectorBuffer, 512, "Not a bootxx image", 18) >= 0 ||
- *((UINT32 *)(SectorBuffer + 1028)) == 0x7886b6d1) {
+ } else if (FindMem(Buffer, 512, "Not a bootxx image", 18) >= 0 ||
+ *((UINT32 *)(Buffer + 1028)) == 0x7886b6d1) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"netbsd";
Volume->OSName = L"NetBSD";
- } else if (FindMem(SectorBuffer, SECTOR_SIZE, "NTLDR", 5) >= 0) {
+ } else if (FindMem(Buffer, SECTOR_SIZE, "NTLDR", 5) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"win";
Volume->OSName = L"Windows";
- } else if (FindMem(SectorBuffer, SECTOR_SIZE, "BOOTMGR", 7) >= 0) {
+ } else if (FindMem(Buffer, SECTOR_SIZE, "BOOTMGR", 7) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"winvista,win";
Volume->OSName = L"Windows";
- } else if (FindMem(SectorBuffer, 512, "CPUBOOT SYS", 11) >= 0 ||
- FindMem(SectorBuffer, 512, "KERNEL SYS", 11) >= 0) {
+ } else if (FindMem(Buffer, 512, "CPUBOOT SYS", 11) >= 0 ||
+ FindMem(Buffer, 512, "KERNEL SYS", 11) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"freedos";
Volume->OSName = L"FreeDOS";
- } else if (FindMem(SectorBuffer, 512, "OS2LDR", 6) >= 0 ||
- FindMem(SectorBuffer, 512, "OS2BOOT", 7) >= 0) {
+ } else if (FindMem(Buffer, 512, "OS2LDR", 6) >= 0 ||
+ FindMem(Buffer, 512, "OS2BOOT", 7) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"ecomstation";
Volume->OSName = L"eComStation";
- } else if (FindMem(SectorBuffer, 512, "Be Boot Loader", 14) >= 0) {
+ } else if (FindMem(Buffer, 512, "Be Boot Loader", 14) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"beos";
Volume->OSName = L"BeOS";
- } else if (FindMem(SectorBuffer, 512, "yT Boot Loader", 14) >= 0) {
+ } else if (FindMem(Buffer, 512, "yT Boot Loader", 14) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"zeta,beos";
Volume->OSName = L"ZETA";
- } else if (FindMem(SectorBuffer, 512, "\x04" "beos\x06" "system\x05" "zbeos", 18) >= 0 ||
- FindMem(SectorBuffer, 512, "\x06" "system\x0c" "haiku_loader", 20) >= 0) {
+ } else if (FindMem(Buffer, 512, "\x04" "beos\x06" "system\x05" "zbeos", 18) >= 0 ||
+ FindMem(Buffer, 512, "\x06" "system\x0c" "haiku_loader", 20) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"haiku,beos";
Volume->OSName = L"Haiku";
@@ -494,21 +592,21 @@ static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootabl
#endif
// dummy FAT boot sector (created by OS X's newfs_msdos)
- if (FindMem(SectorBuffer, 512, "Non-system disk", 15) >= 0)
+ if (FindMem(Buffer, 512, "Non-system disk", 15) >= 0)
Volume->HasBootCode = FALSE;
// dummy FAT boot sector (created by Linux's mkdosfs)
- if (FindMem(SectorBuffer, 512, "This is not a bootable disk", 27) >= 0)
+ if (FindMem(Buffer, 512, "This is not a bootable disk", 27) >= 0)
Volume->HasBootCode = FALSE;
// dummy FAT boot sector (created by Windows)
- if (FindMem(SectorBuffer, 512, "Press any key to restart", 24) >= 0)
+ if (FindMem(Buffer, 512, "Press any key to restart", 24) >= 0)
Volume->HasBootCode = FALSE;
// check for MBR partition table
- if (*((UINT16 *)(SectorBuffer + 510)) == 0xaa55) {
+ if (*((UINT16 *)(Buffer + 510)) == 0xaa55) {
MbrTableFound = FALSE;
- MbrTable = (MBR_PARTITION_INFO *)(SectorBuffer + 446);
+ MbrTable = (MBR_PARTITION_INFO *)(Buffer + 446);
for (i = 0; i < 4; i++)
if (MbrTable[i].StartLBA && MbrTable[i].Size)
MbrTableFound = TRUE;
@@ -526,7 +624,7 @@ static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootabl
CheckError(Status, L"while reading boot sector");
#endif
}
-}
+} /* VOID ScanVolumeBootcode() */
// default volume badge icon based on disk kind
static VOID ScanVolumeDefaultIcon(IN OUT REFIT_VOLUME *Volume)
@@ -544,14 +642,98 @@ static VOID ScanVolumeDefaultIcon(IN OUT REFIT_VOLUME *Volume)
} // switch()
}
-VOID ScanVolume(IN OUT REFIT_VOLUME *Volume)
+// Return a string representing the input size in IEEE-1541 units.
+// The calling function is responsible for freeing the allocated memory.
+static CHAR16 *SizeInIEEEUnits(UINT64 SizeInBytes) {
+ UINT64 SizeInIeee;
+ UINTN Index = 0, NumPrefixes;
+ CHAR16 *Units, *Prefixes = L" KMGTPEZ";
+ CHAR16 *TheValue;
+
+ TheValue = AllocateZeroPool(sizeof(CHAR16) * 256);
+ if (TheValue != NULL) {
+ NumPrefixes = StrLen(Prefixes);
+ SizeInIeee = SizeInBytes;
+ while ((SizeInIeee > 1024) && (Index < (NumPrefixes - 1))) {
+ Index++;
+ SizeInIeee /= 1024;
+ } // while
+ if (Prefixes[Index] == ' ') {
+ Units = StrDuplicate(L"-byte");
+ } else {
+ Units = StrDuplicate(L" iB");
+ Units[1] = Prefixes[Index];
+ } // if/else
+ SPrint(TheValue, 255, L"%ld%s", SizeInIeee, Units);
+ } // if
+ return TheValue;
+} // CHAR16 *SizeInSIUnits()
+
+// Return a name for the volume. Ideally this should be the label for the
+// filesystem it contains, but this function falls back to describing the
+// filesystem by size (200 MiB, etc.) and/or type (ext2, HFS+, etc.), if
+// this information can be extracted.
+// The calling function is responsible for freeing the memory allocated
+// for the name string.
+static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) {
+ EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr;
+ CHAR16 *FoundName = NULL;
+ CHAR16 *SISize, *TypeName;
+
+ FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
+ if (FileSystemInfoPtr != NULL) { // we have filesystem information (size, label)....
+ if ((FileSystemInfoPtr->VolumeLabel != NULL) && (StrLen(FileSystemInfoPtr->VolumeLabel) > 0)) {
+ FoundName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
+ }
+
+ // Special case: rEFInd HFS+ driver always returns label of "HFS+ volume", so wipe
+ // this so that we can build a new name that includes the size....
+ if ((FoundName != NULL) && (StrCmp(FoundName, L"HFS+ volume") == 0) && (Volume->FSType == FS_TYPE_HFSPLUS)) {
+ MyFreePool(FoundName);
+ FoundName = NULL;
+ } // if rEFInd HFS+ driver suspected
+
+ if (FoundName == NULL) { // filesystem has no name, so use fs type and size
+ FoundName = AllocateZeroPool(sizeof(CHAR16) * 256);
+ if (FoundName != NULL) {
+ SISize = SizeInIEEEUnits(FileSystemInfoPtr->VolumeSize);
+ SPrint(FoundName, 255, L"%s%s volume", SISize, FSTypeName(Volume->FSType));
+ MyFreePool(SISize);
+ } // if allocated memory OK
+ } // if (FoundName == NULL)
+
+ FreePool(FileSystemInfoPtr);
+
+ } else { // fs driver not returning info; fall back on our own information....
+ FoundName = AllocateZeroPool(sizeof(CHAR16) * 256);
+ if (FoundName != NULL) {
+ TypeName = FSTypeName(Volume->FSType); // NOTE: Don't free TypeName; function returns constant
+ if (StrLen(TypeName) > 0)
+ SPrint(FoundName, 255, L"%s volume", FSTypeName(Volume->FSType));
+ else
+ SPrint(FoundName, 255, L"unknown volume");
+ } // if allocated memory OK
+ } // if
+
+ // TODO: Above could be improved/extended, in case filesystem name is not found,
+ // such as:
+ // - use partition label
+ // - use or add disk/partition number (e.g., "(hd0,2)")
+
+ // Desperate fallback name....
+ if (FoundName == NULL) {
+ FoundName = StrDuplicate(L"unknown volume");
+ }
+ return FoundName;
+} // static CHAR16 *GetVolumeName()
+
+VOID ScanVolume(REFIT_VOLUME *Volume)
{
EFI_STATUS Status;
EFI_DEVICE_PATH *DevicePath, *NextDevicePath;
EFI_DEVICE_PATH *DiskDevicePath, *RemainingDevicePath;
EFI_HANDLE WholeDiskHandle;
UINTN PartialLength;
- EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr;
BOOLEAN Bootable;
// get device path
@@ -664,20 +846,7 @@ VOID ScanVolume(IN OUT REFIT_VOLUME *Volume)
Volume->IsReadable = TRUE;
}
- // get volume name
- FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
- if (FileSystemInfoPtr != NULL) {
- Volume->VolName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
- FreePool(FileSystemInfoPtr);
- }
-
- if (Volume->VolName == NULL) {
- Volume->VolName = StrDuplicate(L"Unknown");
- }
- // TODO: if no official volume name is found or it is empty, use something else, e.g.:
- // - name from bytes 3 to 10 of the boot sector
- // - partition number
- // - name derived from file system type or partition type
+ Volume->VolName = GetVolumeName(Volume);
// get custom volume icon if present
if (FileExists(Volume->RootDir, VOLUME_BADGE_NAME))
@@ -747,7 +916,7 @@ static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_I
}
}
}
-}
+} /* VOID ScanExtendedPartition() */
VOID ScanVolumes(VOID)
{
@@ -862,7 +1031,7 @@ VOID ScanVolumes(VOID)
MyFreePool(SectorBuffer2);
}
- }
+ } // for
} /* VOID ScanVolumes() */
static VOID UninitVolumes(VOID)
@@ -1207,8 +1376,8 @@ BOOLEAN StriSubCmp(IN CHAR16 *SmallStr, IN CHAR16 *BigStr) {
// Merges two strings, creating a new one and returning a pointer to it.
// If AddChar != 0, the specified character is placed between the two original
-// strings (unless the first string is NULL). The original input string
-// *First is de-allocated and replaced by the new merged string.
+// strings (unless the first string is NULL or empty). The original input
+// string *First is de-allocated and replaced by the new merged string.
// This is similar to StrCat, but safer and more flexible because
// MergeStrings allocates memory that's the correct size for the
// new merged string, so it can take a NULL *First and it cleans
@@ -1224,12 +1393,16 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) {
Length2 = StrLen(Second);
NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2));
if (NewString != NULL) {
+ if ((*First != NULL) && (StrLen(*First) == 0)) {
+ MyFreePool(*First);
+ *First = NULL;
+ }
NewString[0] = L'\0';
if (*First != NULL) {
StrCat(NewString, *First);
if (AddChar) {
NewString[Length1] = AddChar;
- NewString[Length1 + 1] = 0;
+ NewString[Length1 + 1] = '\0';
} // if (AddChar)
} // if (*First != NULL)
if (Second != NULL)
@@ -1463,18 +1636,18 @@ BOOLEAN EjectMedia(VOID) {
} // VOID EjectMedia()
-// Return the GUID as a string, suitable for display to the user. Note that the calling
-// function is responsible for freeing the allocated memory.
-CHAR16 * GuidAsString(EFI_GUID *GuidData) {
- CHAR16 *TheString;
-
- TheString = AllocateZeroPool(42 * sizeof(CHAR16));
- if (TheString != 0) {
- SPrint (TheString, 82, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- (UINTN)GuidData->Data1, (UINTN)GuidData->Data2, (UINTN)GuidData->Data3,
- (UINTN)GuidData->Data4[0], (UINTN)GuidData->Data4[1], (UINTN)GuidData->Data4[2],
- (UINTN)GuidData->Data4[3], (UINTN)GuidData->Data4[4], (UINTN)GuidData->Data4[5],
- (UINTN)GuidData->Data4[6], (UINTN)GuidData->Data4[7]);
- }
- return TheString;
-} // GuidAsString(EFI_GUID *GuidData)
+// // Return the GUID as a string, suitable for display to the user. Note that the calling
+// // function is responsible for freeing the allocated memory.
+// CHAR16 * GuidAsString(EFI_GUID *GuidData) {
+// CHAR16 *TheString;
+//
+// TheString = AllocateZeroPool(42 * sizeof(CHAR16));
+// if (TheString != 0) {
+// SPrint (TheString, 82, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+// (UINTN)GuidData->Data1, (UINTN)GuidData->Data2, (UINTN)GuidData->Data3,
+// (UINTN)GuidData->Data4[0], (UINTN)GuidData->Data4[1], (UINTN)GuidData->Data4[2],
+// (UINTN)GuidData->Data4[3], (UINTN)GuidData->Data4[4], (UINTN)GuidData->Data4[5],
+// (UINTN)GuidData->Data4[6], (UINTN)GuidData->Data4[7]);
+// }
+// return TheString;
+// } // GuidAsString(EFI_GUID *GuidData)
diff --git a/refind/lib.h b/refind/lib.h
index 1e74ac9..4e936a8 100644
--- a/refind/lib.h
+++ b/refind/lib.h
@@ -35,11 +35,11 @@
*/
/*
* Modifications copyright (c) 2012 Roderick W. Smith
- *
+ *
* Modifications distributed under the terms of the GNU General Public
* License (GPL) version 3 (GPLv3), a copy of which must be distributed
* with this source code or binaries made from it.
- *
+ *
*/
#ifndef __LIB_H_
@@ -116,6 +116,6 @@ VOID MyFreePool(IN OUT VOID *Pointer);
BOOLEAN EjectMedia(VOID);
-CHAR16 * GuidAsString(EFI_GUID *GuidData);
+//CHAR16 * GuidAsString(EFI_GUID *GuidData);
#endif
\ No newline at end of file
diff --git a/refind/main.c b/refind/main.c
index 3ff6255..22693f1 100644
--- a/refind/main.c
+++ b/refind/main.c
@@ -56,17 +56,19 @@
#ifdef __MAKEWITH_TIANO
#include "../EfiLib/BdsHelper.h"
+#else
+#define EFI_SECURITY_VIOLATION EFIERR (26)
#endif // __MAKEWITH_TIANO
-//
+//
// variables
-#define MACOSX_LOADER_PATH L"\\System\\Library\\CoreServices\\boot.efi"
+#define MACOSX_LOADER_PATH L"System\\Library\\CoreServices\\boot.efi"
#if defined (EFIX64)
-#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\shellx64.efi"
+#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellx64.efi,\\shellx64.efi"
#define DRIVER_DIRS L"drivers,drivers_x64"
#elif defined (EFI32)
-#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\shellia32.efi"
+#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellia32.efi,\\shellia32.efi"
#define DRIVER_DIRS L"drivers,drivers_ia32"
#else
#define SHELL_NAMES L"\\EFI\\tools\\shell.efi"
@@ -87,17 +89,24 @@
// a ".efi" extension to be found when scanning for boot loaders.
#define LINUX_MATCH_PATTERNS L"vmlinuz*,bzImage*"
+// Default hint text for program-launch submenus
+#define SUBSCREEN_HINT1 L"Use arrow keys to move cursor; Enter to boot;"
+#define SUBSCREEN_HINT2 L"Insert or F2 to edit options; Esc to return to main menu"
+#define SUBSCREEN_HINT2_NO_EDITOR L"Esc to return to main menu"
+
static REFIT_MENU_ENTRY MenuEntryAbout = { L"About rEFInd", TAG_ABOUT, 1, 0, 'A', NULL, NULL, NULL };
static REFIT_MENU_ENTRY MenuEntryReset = { L"Reboot Computer", TAG_REBOOT, 1, 0, 'R', NULL, NULL, NULL };
static REFIT_MENU_ENTRY MenuEntryShutdown = { L"Shut Down Computer", TAG_SHUTDOWN, 1, 0, 'U', NULL, NULL, NULL };
static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 0, 0, 0, NULL, NULL, NULL };
static REFIT_MENU_ENTRY MenuEntryExit = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, NULL, NULL, NULL };
-static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot" };
-static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL };
+static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot",
+ L"Use arrow keys to move cursor; Enter to boot;",
+ 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, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{TAG_SHELL, TAG_APPLE_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }};
// Structure used to hold boot loader filenames and time stamps in
@@ -118,7 +127,7 @@ static VOID AboutrEFInd(VOID)
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.5.0.3");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.0.4");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
@@ -186,7 +195,7 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths,
// set load options
if (LoadOptions != NULL) {
if (LoadOptionsPrefix != NULL) {
- MergeStrings(&FullLoadOptions, LoadOptionsPrefix, 0);
+// MergeStrings(&FullLoadOptions, LoadOptionsPrefix, 0);
MergeStrings(&FullLoadOptions, LoadOptions, L' ');
if (OSType == 'M') {
MergeStrings(&FullLoadOptions, L" ", 0);
@@ -215,9 +224,9 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths,
// TODO: Track down the cause of this error and fix it, if possible.
// ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex],
// ImageData, ImageSize, &ChildImageHandle);
- ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex],
- NULL, 0, &ChildImageHandle);
- if ((Status == EFI_ACCESS_DENIED) && (ShimLoaded())) {
+ ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex],
+ NULL, 0, &ChildImageHandle);
+ if (((Status == EFI_ACCESS_DENIED) || (Status == EFI_SECURITY_VIOLATION)) && (ShimLoaded())) {
FindVolumeAndFilename(DevicePaths[DevicePathIndex], &DeviceVolume, &loader);
if (DeviceVolume != NULL) {
Status = ReadFile(DeviceVolume->RootDir, loader, &File, &ImageSize);
@@ -395,6 +404,8 @@ static REFIT_MENU_SCREEN* CopyMenuScreen(REFIT_MENU_SCREEN *Entry) {
for (i = 0; i < Entry->EntryCount && NewEntry->Entries; i++) {
AddMenuEntry(NewEntry, Entry->Entries[i]);
} // for
+ NewEntry->Hint1 = (Entry->Hint1) ? StrDuplicate(Entry->Hint1) : NULL;
+ NewEntry->Hint2 = (Entry->Hint2) ? StrDuplicate(Entry->Hint2) : NULL;
} // if
return (NewEntry);
} // static REFIT_MENU_SCREEN* CopyMenuScreen()
@@ -455,6 +466,23 @@ 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 = NULL;
+
+ if (Options != NULL)
+ 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 +491,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;
@@ -478,15 +506,18 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) {
// default 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
+ SubEntry->me.Title = StrDuplicate(L"Boot using default options");
+ MainOptions = SubEntry->LoadOptions;
+ SubEntry->LoadOptions = AddInitrdToOptions(MainOptions, SubEntry->InitrdPath);
+ MyFreePool(MainOptions);
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
} // if (SubEntry != NULL)
+ SubScreen->Hint1 = StrDuplicate(SUBSCREEN_HINT1);
+ if (GlobalConfig.HideUIFlags & HIDEUI_FLAG_EDITOR) {
+ SubScreen->Hint2 = StrDuplicate(SUBSCREEN_HINT2_NO_EDITOR);
+ } else {
+ SubScreen->Hint2 = StrDuplicate(SUBSCREEN_HINT2);
+ } // if/else
} // if (SubScreen != NULL)
} else { // existing subscreen; less initialization, and just add new entry later....
SubScreen = Entry->me.SubScreen;
@@ -497,7 +528,7 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) {
VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) {
REFIT_MENU_SCREEN *SubScreen;
LOADER_ENTRY *SubEntry;
- CHAR16 *InitrdOption = NULL, *Temp;
+ CHAR16 *InitrdName;
CHAR16 DiagsFileName[256];
REFIT_FILE *File;
UINTN TokenCount;
@@ -567,7 +598,7 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) {
} // not single-user
// check for Apple hardware diagnostics
- StrCpy(DiagsFileName, L"\\System\\Library\\CoreServices\\.diagnostics\\diags.efi");
+ StrCpy(DiagsFileName, L"System\\Library\\CoreServices\\.diagnostics\\diags.efi");
if (FileExists(Volume->RootDir, DiagsFileName) && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HWTEST)) {
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
@@ -583,24 +614,26 @@ 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);
- }
- TokenCount = ReadTokenLine(File, &TokenList); // read and discard first entry, since it's
- FreeTokenLine(&TokenList, &TokenCount); // set up by InitializeSubScreen(), earlier....
+ InitrdName = FindInitrd(Entry->LoaderPath, Volume);
+ TokenCount = ReadTokenLine(File, &TokenList);
+ // first entry requires special processing, since it was initially set
+ // up with a default title but correct options by InitializeSubScreen(),
+ // earlier....
+ if ((SubScreen->Entries != NULL) && (SubScreen->Entries[0] != NULL)) {
+ MyFreePool(SubScreen->Entries[0]->Title);
+ SubScreen->Entries[0]->Title = StrDuplicate(TokenList[0]);
+ } // if
+ FreeTokenLine(&TokenList, &TokenCount);
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], InitrdName);
FreeTokenLine(&TokenList, &TokenCount);
SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX;
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
} // while
- MyFreePool(InitrdOption);
- MyFreePool(Temp);
+ MyFreePool(InitrdName);
MyFreePool(File);
} // if Linux options file exists
@@ -680,32 +713,31 @@ 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
// code and shortcut letter. For Linux EFI stub loaders, also sets kernel options
// that will (with luck) work fairly automatically.
-VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
- CHAR16 IconFileName[256];
- CHAR16 *FileName, *PathOnly, *OSIconName = NULL, *Temp;
- CHAR16 ShortcutLetter = 0;
+VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, REFIT_VOLUME *Volume) {
+ CHAR16 IconFileName[256];
+ CHAR16 *FileName, *PathOnly, *OSIconName = NULL, *Temp, *SubString;
+ CHAR16 ShortcutLetter = 0;
+ UINTN i, Length;
FileName = Basename(LoaderPath);
PathOnly = FindPath(LoaderPath);
// locate a custom icon for the loader
+ // Anything found here takes precedence over the "hints" in the OSIconName variable
StrCpy(IconFileName, LoaderPath);
ReplaceEfiExtension(IconFileName, L".icns");
if (FileExists(Volume->RootDir, IconFileName)) {
@@ -714,6 +746,8 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME
Entry->me.Image = Volume->VolIconImage;
} // icon matched to loader or volume
+ // Begin creating icon "hints" by using last part of directory path leading
+ // to the loader
Temp = FindLastDirName(LoaderPath);
MergeStrings(&OSIconName, Temp, L',');
MyFreePool(Temp);
@@ -722,6 +756,26 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME
ShortcutLetter = OSIconName[0];
}
+ // Add every "word" in the volume label, delimited by spaces, dashes (-), or
+ // underscores (_), to the list of hints to be used in searching for OS
+ // icons.
+ if ((Volume->VolName) && (StrLen(Volume->VolName) > 0)) {
+ Temp = SubString = StrDuplicate(Volume->VolName);
+ if (Temp != NULL) {
+ Length = StrLen(Temp);
+ for (i = 0; i < Length; i++) {
+ if ((Temp[i] == L' ') || (Temp[i] == L'_') || (Temp[i] == L'-')) {
+ Temp[i] = 0;
+ if (StrLen(SubString) > 0)
+ MergeStrings(&OSIconName, SubString, L',');
+ SubString = Temp + i + 1;
+ } // if
+ } // for
+ MergeStrings(&OSIconName, SubString, L',');
+ MyFreePool(Temp);
+ } // if
+ } // if
+
// detect specific loaders
if (StriSubCmp(L"bzImage", LoaderPath) || StriSubCmp(L"vmlinuz", LoaderPath)) {
MergeStrings(&OSIconName, L"linux", L',');
@@ -747,12 +801,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;
@@ -762,7 +810,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME
Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_GRUB;
} else if (StriCmp(FileName, L"cdboot.efi") == 0 ||
StriCmp(FileName, L"bootmgr.efi") == 0 ||
- StriCmp(FileName, L"Bootmgfw.efi") == 0) {
+ StriCmp(FileName, L"bootmgfw.efi") == 0) {
MergeStrings(&OSIconName, L"win", L',');
Entry->OSType = 'W';
ShortcutLetter = 'W';
@@ -816,12 +864,11 @@ LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN
// (Time1 == Time2). Precision is only to the nearest second; since
// this is used for sorting boot loader entries, differences smaller
// than this are likely to be meaningless (and unlikely!).
-INTN TimeComp(EFI_TIME *Time1, EFI_TIME *Time2) {
+INTN TimeComp(IN EFI_TIME *Time1, IN EFI_TIME *Time2) {
INT64 Time1InSeconds, Time2InSeconds;
// Following values are overestimates; I'm assuming 31 days in every month.
- // This is fine for the purpose of this function, which has a limited
- // purpose.
+ // This is fine for the purpose of this function, which is limited
Time1InSeconds = Time1->Second + (Time1->Minute * 60) + (Time1->Hour * 3600) + (Time1->Day * 86400) +
(Time1->Month * 2678400) + ((Time1->Year - 1998) * 32140800);
Time2InSeconds = Time2->Second + (Time2->Minute * 60) + (Time2->Hour * 3600) + (Time2->Day * 86400) +
@@ -880,8 +927,10 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *P
CHAR16 FileName[256], *Extension;
struct LOADER_LIST *LoaderList = NULL, *NewLoader;
- if ((!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && Volume->DeviceHandle != SelfVolume->DeviceHandle) ||
- (StriCmp(Path, SelfDirPath) != 0)) && (!IsIn(Path, GlobalConfig.DontScanDirs))) {
+ if ((!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && (Volume->DeviceHandle != SelfVolume->DeviceHandle)) ||
+ (StriCmp(Path, SelfDirPath) != 0)) &&
+ (!IsIn(Path, GlobalConfig.DontScanDirs)) &&
+ (!IsIn(Volume->VolName, GlobalConfig.DontScanVolumes))) {
// look through contents of the directory
DirIterOpen(Volume->RootDir, Path, &DirIter);
while (DirIterNext(&DirIter, 2, Pattern, &DirEntry)) {
@@ -893,9 +942,9 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *P
continue; // skip this
if (Path)
- SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName);
+ SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName);
else
- SPrint(FileName, 255, L"\\%s", DirEntry->FileName);
+ SPrint(FileName, 255, L"\\%s", DirEntry->FileName);
CleanUpPathNameSlashes(FileName);
NewLoader = AllocateZeroPool(sizeof(struct LOADER_LIST));
if (NewLoader != NULL) {
@@ -935,22 +984,22 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) {
if ((Volume->RootDir != NULL) && (Volume->VolName != NULL)) {
// check for Mac OS X boot loader
- if (!IsIn(L"\\System\\Library\\CoreServices", GlobalConfig.DontScanDirs)) {
+ if (!IsIn(L"System\\Library\\CoreServices", GlobalConfig.DontScanDirs)) {
StrCpy(FileName, MACOSX_LOADER_PATH);
if (FileExists(Volume->RootDir, FileName) && !IsIn(L"boot.efi", GlobalConfig.DontScanFiles)) {
AddLoaderEntry(FileName, L"Mac OS X", Volume);
}
// check for XOM
- StrCpy(FileName, L"\\System\\Library\\CoreServices\\xom.efi");
+ StrCpy(FileName, L"System\\Library\\CoreServices\\xom.efi");
if (FileExists(Volume->RootDir, FileName) && !IsIn(L"boot.efi", GlobalConfig.DontScanFiles)) {
AddLoaderEntry(FileName, L"Windows XP (XoM)", Volume);
}
} // if Mac directory not in GlobalConfig.DontScanDirs list
// check for Microsoft boot loader/menu
- StrCpy(FileName, L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi");
- if (FileExists(Volume->RootDir, FileName) && !IsIn(L"\\EFI\\Microsoft\\Boot", GlobalConfig.DontScanDirs) &&
+ StrCpy(FileName, L"EFI\\Microsoft\\Boot\\Bootmgfw.efi");
+ if (FileExists(Volume->RootDir, FileName) && !IsIn(L"EFI\\Microsoft\\Boot", GlobalConfig.DontScanDirs) &&
!IsIn(L"bootmgfw.efi", GlobalConfig.DontScanFiles)) {
AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume);
}
@@ -963,7 +1012,7 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) {
while (DirIterNext(&EfiDirIter, 1, NULL, &EfiDirEntry)) {
if (StriCmp(EfiDirEntry->FileName, L"tools") == 0 || EfiDirEntry->FileName[0] == '.')
continue; // skip this, doesn't contain boot loaders
- SPrint(FileName, 255, L"\\EFI\\%s", EfiDirEntry->FileName);
+ SPrint(FileName, 255, L"EFI\\%s", EfiDirEntry->FileName);
ScanLoaderDir(Volume, FileName, MatchPatterns);
} // while()
Status = DirIterClose(&EfiDirIter);
@@ -1262,6 +1311,12 @@ static LEGACY_ENTRY * AddLegacyEntry(IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Vo
SubScreen->Title = AllocateZeroPool(256 * sizeof(CHAR16));
SPrint(SubScreen->Title, 255, L"Boot Options for %s on %s", LoaderTitle, VolDesc);
SubScreen->TitleImage = Entry->me.Image;
+ SubScreen->Hint1 = StrDuplicate(SUBSCREEN_HINT1);
+ if (GlobalConfig.HideUIFlags & HIDEUI_FLAG_EDITOR) {
+ SubScreen->Hint2 = StrDuplicate(SUBSCREEN_HINT2_NO_EDITOR);
+ } else {
+ SubScreen->Hint2 = StrDuplicate(SUBSCREEN_HINT2);
+ } // if/else
// default entry
SubEntry = AllocateZeroPool(sizeof(LEGACY_ENTRY));
@@ -1330,6 +1385,12 @@ static LEGACY_ENTRY * AddLegacyEntryUEFI(BDS_COMMON_OPTION *BdsOption, IN UINT16
SubScreen->Title = AllocateZeroPool(256 * sizeof(CHAR16));
SPrint(SubScreen->Title, 255, L"No boot options for legacy target");
SubScreen->TitleImage = Entry->me.Image;
+ SubScreen->Hint1 = StrDuplicate(SUBSCREEN_HINT1);
+ if (GlobalConfig.HideUIFlags & HIDEUI_FLAG_EDITOR) {
+ SubScreen->Hint2 = StrDuplicate(SUBSCREEN_HINT2_NO_EDITOR);
+ } else {
+ SubScreen->Hint2 = StrDuplicate(SUBSCREEN_HINT2);
+ } // if/else
// default entry
SubEntry = AllocateZeroPool(sizeof(LEGACY_ENTRY));
@@ -1363,7 +1424,6 @@ static VOID ScanLegacyUEFI(IN UINTN DiskType)
BDS_COMMON_OPTION *BdsOption;
LIST_ENTRY TempList;
BBS_BBS_DEVICE_PATH * BbsDevicePath = NULL;
-// REFIT_VOLUME Volume;
InitializeListHead (&TempList);
ZeroMem (Buffer, sizeof (Buffer));
@@ -1805,16 +1865,16 @@ static VOID ScanForTools(VOID) {
break;
case TAG_GPTSYNC:
MyFreePool(FileName);
- FileName = NULL;
- MergeStrings(&FileName, L"\\efi\\tools\\gptsync.efi", 0);
+ FileName = StrDuplicate(L"\\efi\\tools\\gptsync.efi");
+// MergeStrings(&FileName, L"\\efi\\tools\\gptsync.efi", 0);
if (FileExists(SelfRootDir, FileName)) {
AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"Make Hybrid MBR", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'P', FALSE);
}
break;
case TAG_APPLE_RECOVERY:
MyFreePool(FileName);
- FileName = NULL;
- MergeStrings(&FileName, L"\\com.apple.recovery.boot\\boot.efi", 0);
+ FileName = StrDuplicate(L"\\com.apple.recovery.boot\\boot.efi");
+// MergeStrings(&FileName, L"\\com.apple.recovery.boot\\boot.efi", 0);
for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
if ((Volumes[VolumeIndex]->RootDir != NULL) && (FileExists(Volumes[VolumeIndex]->RootDir, FileName))) {
SPrint(Description, 255, L"Apple Recovery on %s", Volumes[VolumeIndex]->VolName);
@@ -1860,7 +1920,7 @@ VOID RescanAll(VOID) {
FreeList((VOID ***) &(MainMenu.Entries), &MainMenu.EntryCount);
MainMenu.Entries = NULL;
MainMenu.EntryCount = 0;
- ReadConfig();
+ ReadConfig(CONFIG_FILE_NAME);
ConnectAllDriversToAllControllers();
ScanVolumes();
ScanForBootloaders();
@@ -1889,7 +1949,7 @@ static VOID InitializeLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *System
//
EFI_STATUS
EFIAPI
-efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
+efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status;
BOOLEAN MainLoopRunning = TRUE;
@@ -1910,7 +1970,7 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
FindLegacyBootType();
if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC)
CopyMem(GlobalConfig.ScanFor, "ihebocm ", NUM_SCAN_OPTIONS);
- ReadConfig();
+ ReadConfig(CONFIG_FILE_NAME);
WarnIfLegacyProblems();
MainMenu.TimeoutSeconds = GlobalConfig.Timeout;
diff --git a/refind/menu.c b/refind/menu.c
index a6e72ad..7de9d8b 100644
--- a/refind/menu.c
+++ b/refind/menu.c
@@ -35,11 +35,11 @@
*/
/*
* Modifications copyright (c) 2012 Roderick W. Smith
- *
+ *
* Modifications distributed under the terms of the GNU General Public
* License (GPL) version 3 (GPLv3), a copy of which must be distributed
* with this source code or binaries made from it.
- *
+ *
*/
#include "global.h"
@@ -61,6 +61,7 @@
#define MENU_FUNCTION_PAINT_ALL (2)
#define MENU_FUNCTION_PAINT_SELECTION (3)
#define MENU_FUNCTION_PAINT_TIMEOUT (4)
+#define MENU_FUNCTION_PAINT_HINTS (5)
typedef VOID (*MENU_STYLE_FUNC)(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText);
@@ -357,7 +358,8 @@ static VOID IdentifyRows(IN SCROLL_STATE *State, IN REFIT_MENU_SCREEN *Screen) {
//
// generic menu function
//
-static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC StyleFunc, IN INTN DefaultEntryIndex, OUT REFIT_MENU_ENTRY **ChosenEntry)
+static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC StyleFunc, IN OUT INTN *DefaultEntryIndex,
+ OUT REFIT_MENU_ENTRY **ChosenEntry)
{
SCROLL_STATE State;
EFI_STATUS Status;
@@ -379,10 +381,11 @@ static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC Sty
StyleFunc(Screen, &State, MENU_FUNCTION_INIT, NULL);
IdentifyRows(&State, Screen);
// override the starting selection with the default index, if any
- if (DefaultEntryIndex >= 0 && DefaultEntryIndex <= State.MaxIndex) {
- State.CurrentSelection = DefaultEntryIndex;
+ if (*DefaultEntryIndex >= 0 && *DefaultEntryIndex <= State.MaxIndex) {
+ State.CurrentSelection = *DefaultEntryIndex;
UpdateScroll(&State, SCROLL_NONE);
}
+ State.PaintAll = TRUE;
while (!MenuExit) {
// update the screen
@@ -485,6 +488,7 @@ static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC Sty
if (ChosenEntry)
*ChosenEntry = Screen->Entries[State.CurrentSelection];
+ *DefaultEntryIndex = State.CurrentSelection;
return MenuExit;
} /* static UINTN RunGenericMenu() */
@@ -508,7 +512,7 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
MenuPosY = 4;
if (Screen->InfoLineCount > 0)
MenuPosY += Screen->InfoLineCount + 1;
- MenuHeight = ConHeight - MenuPosY;
+ MenuHeight = ConHeight - MenuPosY - 3;
if (Screen->TimeoutSeconds > 0)
MenuHeight -= 2;
InitScroll(State, Screen->EntryCount, MenuHeight);
@@ -520,8 +524,9 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
if (MenuWidth < ItemWidth)
MenuWidth = ItemWidth;
}
- if (MenuWidth > ConWidth - 6)
- MenuWidth = ConWidth - 6;
+ MenuWidth += 2;
+ if (MenuWidth > ConWidth - 3)
+ MenuWidth = ConWidth - 3;
// prepare strings for display
DisplayStrings = AllocatePool(sizeof(CHAR16 *) * Screen->EntryCount);
@@ -589,14 +594,26 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, ArrowDown);
else
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, L" ");
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) {
+ if (Screen->Hint1 != NULL) {
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 2);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, Screen->Hint1);
+ }
+ if (Screen->Hint2 != NULL) {
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 1);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, Screen->Hint2);
+ }
+ }
break;
case MENU_FUNCTION_PAINT_SELECTION:
// redraw selection cursor
- refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2, MenuPosY + (State->PreviousSelection - State->FirstVisible));
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2,
+ MenuPosY + (State->PreviousSelection - State->FirstVisible));
refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_BASIC);
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[State->PreviousSelection]);
- refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2, MenuPosY + (State->CurrentSelection - State->FirstVisible));
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2,
+ MenuPosY + (State->CurrentSelection - State->FirstVisible));
refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_CURRENT);
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[State->CurrentSelection]);
break;
@@ -605,12 +622,12 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
if (ParamText[0] == 0) {
// clear message
refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
- refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 1);
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 3);
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, BlankLine + 1);
} else {
// paint or update message
refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR);
- refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, ConHeight - 1);
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, ConHeight - 3);
SPrint(TimeoutMessage, 255, L"%s ", ParamText);
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, TimeoutMessage);
}
@@ -704,6 +721,16 @@ static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *Sta
DrawMenuText(Screen->Entries[i]->Title, (i == State->CurrentSelection) ? MenuWidth : 0,
EntriesPosX, EntriesPosY + i * TEXT_LINE_HEIGHT);
}
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) {
+ if ((Screen->Hint1 != NULL) && (StrLen(Screen->Hint1) > 0)) {
+ DrawMenuText(Screen->Hint1, 0, (UGAWidth - (StrLen(Screen->Hint1) * FONT_CELL_WIDTH)) / 2,
+ UGAHeight - (FONT_CELL_HEIGHT * 3));
+ }
+ if ((Screen->Hint2 != NULL) && (StrLen(Screen->Hint2) > 0)) {
+ DrawMenuText(Screen->Hint2, 0, (UGAWidth - (StrLen(Screen->Hint2) * FONT_CELL_WIDTH)) / 2,
+ UGAHeight - (FONT_CELL_HEIGHT * 2));
+ } // if
+ } // if
break;
case MENU_FUNCTION_PAINT_SELECTION:
@@ -774,6 +801,11 @@ static VOID PaintAll(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN
if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL))
DrawMainMenuText(Screen->Entries[State->CurrentSelection]->Title,
(UGAWidth - LAYOUT_TEXT_WIDTH) >> 1, textPosY);
+
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) {
+ DrawMainMenuText(Screen->Hint1, (UGAWidth - LAYOUT_TEXT_WIDTH) / 2, UGAHeight - (FONT_CELL_HEIGHT * 3));
+ DrawMainMenuText(Screen->Hint2, (UGAWidth - LAYOUT_TEXT_WIDTH) / 2, UGAHeight - (FONT_CELL_HEIGHT * 2));
+ } // if
} // static VOID PaintAll()
// Move the selection to State->CurrentSelection, adjusting icon row if necessary...
@@ -923,21 +955,18 @@ VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT
static BOOLEAN EditOptions(LOADER_ENTRY *MenuEntry) {
UINTN x_max, y_max;
CHAR16 *EditedOptions;
- EG_PIXEL DarkBackgroundPixel = { 0x0, 0x0, 0x0, 0 };
BOOLEAN retval = FALSE;
+ if (GlobalConfig.HideUIFlags & HIDEUI_FLAG_EDITOR) {
+ return FALSE;
+ }
+
refit_call4_wrapper(ST->ConOut->QueryMode, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max);
if (!GlobalConfig.TextOnly)
SwitchToText(TRUE);
- egClearScreen(&DarkBackgroundPixel);
-
- refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, y_max - 1);
- refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut,
- L"Use cursor keys to edit, Esc to exit, Enter to boot with edited options");
-
- if (line_edit(MenuEntry->LoadOptions, &EditedOptions, x_max, 1)) {
+ if (line_edit(MenuEntry->LoadOptions, &EditedOptions, x_max)) {
MyFreePool(MenuEntry->LoadOptions);
MenuEntry->LoadOptions = EditedOptions;
retval = TRUE;
@@ -953,12 +982,13 @@ static BOOLEAN EditOptions(LOADER_ENTRY *MenuEntry) {
UINTN RunMenu(IN REFIT_MENU_SCREEN *Screen, OUT REFIT_MENU_ENTRY **ChosenEntry)
{
+ INTN DefaultEntry = -1;
MENU_STYLE_FUNC Style = TextMenuStyle;
if (AllowGraphicsMode)
Style = GraphicsMenuStyle;
- return RunGenericMenu(Screen, Style, -1, ChosenEntry);
+ return RunGenericMenu(Screen, Style, &DefaultEntry, ChosenEntry);
}
UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT REFIT_MENU_ENTRY **ChosenEntry)
@@ -967,12 +997,12 @@ UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT
MENU_STYLE_FUNC MainStyle = TextMenuStyle;
REFIT_MENU_ENTRY *TempChosenEntry;
UINTN MenuExit = 0;
- UINTN DefaultEntryIndex = -1;
+ INTN DefaultEntryIndex = -1;
+ INTN DefaultSubmenuIndex = -1;
if (DefaultSelection != NULL) {
// Find a menu entry that includes *DefaultSelection as a substring
DefaultEntryIndex = FindMenuShortcutEntry(Screen, DefaultSelection);
- // If that didn't work, should we scan more characters? For now, no.
}
if (AllowGraphicsMode) {
@@ -981,18 +1011,22 @@ UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT
}
while (!MenuExit) {
- MenuExit = RunGenericMenu(Screen, MainStyle, DefaultEntryIndex, &TempChosenEntry);
+ MenuExit = RunGenericMenu(Screen, MainStyle, &DefaultEntryIndex, &TempChosenEntry);
Screen->TimeoutSeconds = 0;
- if (MenuExit == MENU_EXIT_DETAILS && TempChosenEntry->SubScreen != NULL) {
- MenuExit = RunGenericMenu(TempChosenEntry->SubScreen, Style, -1, &TempChosenEntry);
- if (MenuExit == MENU_EXIT_ESCAPE || TempChosenEntry->Tag == TAG_RETURN)
- MenuExit = 0;
- if (MenuExit == MENU_EXIT_DETAILS) {
- if (!EditOptions((LOADER_ENTRY *) TempChosenEntry))
- MenuExit = 0;
- } // if
- }
+ if (MenuExit == MENU_EXIT_DETAILS) {
+ if (TempChosenEntry->SubScreen != NULL) {
+ MenuExit = RunGenericMenu(TempChosenEntry->SubScreen, Style, &DefaultSubmenuIndex, &TempChosenEntry);
+ if (MenuExit == MENU_EXIT_ESCAPE || TempChosenEntry->Tag == TAG_RETURN)
+ MenuExit = 0;
+ if (MenuExit == MENU_EXIT_DETAILS) {
+ if (!EditOptions((LOADER_ENTRY *) TempChosenEntry))
+ MenuExit = 0;
+ } // if
+ } else { // no sub-screen; ignore keypress
+ MenuExit = 0;
+ }
+ } // Enter sub-screen
}
if (ChosenEntry)
diff --git a/refind/mok.h b/refind/mok.h
index 4fbfb22..d9545d5 100644
--- a/refind/mok.h
+++ b/refind/mok.h
@@ -4,6 +4,7 @@
#define SHIM_LOCK_GUID \
{ 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+#if defined (EFIX64)
typedef struct _SHIM_LOCK
{
EFI_STATUS __attribute__((sysv_abi)) (*shim_verify) (VOID *buffer, UINT32 size);
@@ -13,6 +14,17 @@ typedef struct _SHIM_LOCK
EFI_STATUS __attribute__((sysv_abi)) (*read_header) (void *data, unsigned int datasize,
GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context);
} SHIM_LOCK;
+#else
+typedef struct _SHIM_LOCK
+{
+ EFI_STATUS (*shim_verify) (VOID *buffer, UINT32 size);
+ EFI_STATUS (*generate_hash) (char *data, int datasize,
+ GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context, UINT8 *sha256hash,
+ UINT8 *sha1hash);
+ EFI_STATUS (*read_header) (void *data, unsigned int datasize,
+ GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context);
+} SHIM_LOCK;
+#endif
BOOLEAN ShimLoaded(void);
BOOLEAN secure_mode (VOID);
diff --git a/refind/screen.c b/refind/screen.c
index cd5c698..32711d6 100644
--- a/refind/screen.c
+++ b/refind/screen.c
@@ -33,11 +33,20 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * Modifications copyright (c) 2012 Roderick W. Smith
+ *
+ * Modifications distributed under the terms of the GNU General Public
+ * License (GPL) version 3 (GPLv3), a copy of which must be distributed
+ * with this source code or binaries made from it.
+ *
+ */
#include "global.h"
#include "screen.h"
#include "config.h"
#include "libegint.h"
+#include "lib.h"
#include "../include/refit_call_wrapper.h"
#include "../include/egemb_refind_banner.h"
@@ -46,7 +55,7 @@
UINTN ConWidth;
UINTN ConHeight;
-CHAR16 *BlankLine;
+CHAR16 *BlankLine = NULL;
static VOID DrawScreenHeader(IN CHAR16 *Title);
@@ -58,6 +67,7 @@ BOOLEAN AllowGraphicsMode;
EG_PIXEL StdBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 };
EG_PIXEL MenuBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 };
+EG_PIXEL DarkBackgroundPixel = { 0x0, 0x0, 0x0, 0 };
static BOOLEAN GraphicsScreenDirty;
@@ -65,14 +75,23 @@ static BOOLEAN GraphicsScreenDirty;
static BOOLEAN haveError = FALSE;
+static VOID PrepareBlankLine(VOID) {
+ UINTN i;
+
+ MyFreePool(BlankLine);
+ // make a buffer for a whole text line
+ BlankLine = AllocatePool((ConWidth + 1) * sizeof(CHAR16));
+ for (i = 0; i < ConWidth; i++)
+ BlankLine[i] = ' ';
+ BlankLine[i] = 0;
+}
+
//
// Screen initialization and switching
//
VOID InitScreen(VOID)
{
- UINTN i;
-
// initialize libeg
egInitScreen();
@@ -95,11 +114,7 @@ VOID InitScreen(VOID)
ConHeight = 25;
}
- // make a buffer for a whole text line
- BlankLine = AllocatePool((ConWidth + 1) * sizeof(CHAR16));
- for (i = 0; i < ConWidth; i++)
- BlankLine[i] = ' ';
- BlankLine[i] = 0;
+ PrepareBlankLine();
// show the banner (even when in graphics mode)
DrawScreenHeader(L"Initializing...");
@@ -107,8 +122,10 @@ VOID InitScreen(VOID)
VOID SetupScreen(VOID)
{
- if ((GlobalConfig.RequestedScreenWidth > 0) && (GlobalConfig.RequestedScreenHeight > 0) &&
- egSetScreenSize(GlobalConfig.RequestedScreenWidth, GlobalConfig.RequestedScreenHeight)) {
+ GlobalConfig.RequestedTextMode = egSetTextMode(GlobalConfig.RequestedTextMode);
+
+ if ((GlobalConfig.RequestedScreenWidth > 0) &&
+ (egSetScreenSize(&GlobalConfig.RequestedScreenWidth, &GlobalConfig.RequestedScreenHeight))) {
UGAWidth = GlobalConfig.RequestedScreenWidth;
UGAHeight = GlobalConfig.RequestedScreenHeight;
} // if user requested a particular screen resolution
@@ -136,6 +153,7 @@ VOID SwitchToText(IN BOOLEAN CursorEnabled)
ConWidth = 80;
ConHeight = 25;
}
+ PrepareBlankLine();
}
VOID SwitchToGraphics(VOID)
@@ -172,8 +190,6 @@ VOID FinishTextScreen(IN BOOLEAN WaitAlways)
VOID BeginExternalScreen(IN BOOLEAN UseGraphicsMode, IN CHAR16 *Title)
{
- EG_PIXEL DarkBackgroundPixel = { 0x0, 0x0, 0x0, 0 };
-
if (!AllowGraphicsMode)
UseGraphicsMode = FALSE;
@@ -185,9 +201,6 @@ VOID BeginExternalScreen(IN BOOLEAN UseGraphicsMode, IN CHAR16 *Title)
DrawScreenHeader(Title);
} // if/else
- // show the header
-// DrawScreenHeader(Title);
-
if (!UseGraphicsMode)
SwitchToText(TRUE);
@@ -205,6 +218,9 @@ VOID FinishExternalScreen(VOID)
PauseForKey();
}
+ // Reset the screen resolution, in case external program changed it....
+ SetupScreen();
+
// reset error flag
haveError = FALSE;
}
@@ -224,8 +240,9 @@ static VOID DrawScreenHeader(IN CHAR16 *Title)
UINTN y;
// clear to black background
+ egClearScreen(&DarkBackgroundPixel); // first clear in graphics mode
refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
- refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut);
+ refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut); // then clear in text mode
// paint header background
refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BANNER);
@@ -523,16 +540,22 @@ static void cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len)
(*first)++;
}
-BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max, UINTN y_pos) {
+BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max) {
CHAR16 *line;
UINTN size;
UINTN len;
UINTN first;
+ UINTN y_pos = 3;
CHAR16 *print;
UINTN cursor;
BOOLEAN exit;
BOOLEAN enter;
+ DrawScreenHeader(L"Line Editor");
+ refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, (ConWidth - 71) / 2, ConHeight - 1);
+ refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut,
+ L"Use cursor keys to edit, Esc to exit, Enter to boot with edited options");
+
if (!line_in)
line_in = L"";
size = StrLen(line_in) + 1024;
diff --git a/refind/screen.h b/refind/screen.h
index b89fe8f..b03f6e1 100644
--- a/refind/screen.h
+++ b/refind/screen.h
@@ -105,6 +105,6 @@ VOID BltImageAlpha(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos, IN EG_PIXEL
//VOID BltImageComposite(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN UINTN XPos, IN UINTN YPos);
VOID BltImageCompositeBadge(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN EG_IMAGE *BadgeImage, IN UINTN XPos, IN UINTN YPos);
-BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max, UINTN y_pos);
+BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max);
#endif