]> code.delx.au - refind/commitdiff
Merge branch 'master' of git://git.code.sf.net/p/refind/code
authorStefan Agner <stefan@agner.ch>
Thu, 20 Dec 2012 18:39:07 +0000 (19:39 +0100)
committerStefan Agner <stefan@agner.ch>
Thu, 20 Dec 2012 18:39:07 +0000 (19:39 +0100)
40 files changed:
BUILDING.txt
CREDITS.txt
NEWS.txt
docs/refind/bootmode.html
docs/refind/configfile.html
docs/refind/drivers.html
docs/refind/features.html
docs/refind/getting.html
docs/refind/index.html
docs/refind/installing.html
docs/refind/linux.html
docs/refind/revisions.html
docs/refind/secureboot.html
docs/refind/themes.html
docs/refind/todo.html
docs/refind/using.html
filesystems/fsw_efi.c
icons/transparent.icns [new file with mode: 0644]
install.sh
keys/README.txt [new file with mode: 0644]
keys/canonical-uefi-ca.der [new file with mode: 0644]
keys/refind.cer [new file with mode: 0644]
keys/refind.crt [new file with mode: 0644]
libeg/libeg.h
libeg/libegint.h
libeg/screen.c
libeg/text.c
mkdistrib
mkrlconf.sh [new file with mode: 0755]
refind.conf-sample
refind/config.c
refind/config.h
refind/global.h
refind/lib.c
refind/lib.h
refind/main.c
refind/menu.c
refind/mok.h
refind/screen.c
refind/screen.h

index e5501c2c6d91f2e1957d052fb1b575e0ad74ab84..b69df9b3aca72a39f83720bc26f125e4b273ea6e 100644 (file)
@@ -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
index d8efcdedb0fe36449253d6adf78e0b9f05f928a4..469d6630b9887a03af463e19dfc8202c11253998 100644 (file)
@@ -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.
index c9277003cd5e9110e80fa0b8837f369aed49918b..e249ef829705fe63a0e1107d5f4ce3235c7ddcc4 100644 (file)
--- 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).
 
index 15e5218ab6a8e2906c238d6fd610d39f6d471cde..07fb6ea9404973b3d015f78017ecc741ca2d15cc 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>\r
 \r
 <p>Originally written: 3/14/2012; last Web page update:\r
-12/6/2012, referencing rEFInd 0.5.0</p>\r
+12/16/2012, referencing rEFInd 0.6.0</p>\r
 \r
 \r
 <p>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!</p>\r
@@ -108,7 +108,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 \r
 <p>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 <a href="http://www.rodsbooks.com/gb-hybrid-efi/">my Web page on this EFI implementation</a> for details.)</p>\r
 \r
-<p>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.</p>\r
+<p>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 <i>CSM,</i> which of course will be baffling to the uninitiated. (I referred to it earlier. It's the <i>Compatibility Support Module</i>&mdash;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.</p>\r
 \r
 <p>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.</p>\r
 \r
index dcf1fe10392890fa94ab0bf835d0b472f850292d..2f33216631b2bca04c07e41db42892f5215d1190 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
@@ -104,21 +104,25 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>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.</p>
 
-<p>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:</p>
+<p>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:</p>
 
 <ul>
 
+<li>You can name an icon file after your boot loader, but with an extension of <tt>.icns</tt>. For instance, if you're using <tt class="variable">loader</tt><tt>.efi</tt>, you would name the icon file <tt class="variable">loader</tt><tt>.icns</tt>. (If you use the <tt>scan_all_linux_kernels</tt> option, you can give an icon for a Linux kernel without a <tt>.efi</tt> extension a name based on the kernel name but with a <tt>.icns</tt> extension&mdash;for instance, <tt>bzImage-3.3.2.icns</tt> will serve as the icon for the <tt>bzImage-3.3.2</tt> kernel.) These icon files should be 128x128 images in <a href="http://en.wikipedia.org/wiki/Apple_Icon_Image_format">Apple's ICNS format.</a> You can create such files easily in OS X or convert PNG files to ICNS format with <a href="http://icns.sourceforge.net/">libicns.</a></li>
+
 <li>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 <tt>os_<tt class="variable">name</tt>.icns</tt>. To use this icon, you would place the boot loader in the directory called <tt class="variable">name</tt>.</li>
 
-<li>You can name an icon file after your boot loader, but with an extension of <tt>.icns</tt>. For instance, if you're using <tt class="variable">loader</tt><tt>.efi</tt>, you would name the icon file <tt class="variable">loader</tt><tt>.icns</tt>. (If you use the <tt>scan_all_linux_kernels</tt> option, you can give an icon for a Linux kernel without a <tt>.efi</tt> extension a name based on the kernel name but with a <tt>.icns</tt> extension&mdash;for instance, <tt>bzImage-3.3.2.icns</tt> will serve as the icon for the <tt>bzImage-3.3.2</tt> kernel.) These icon files should be 128x128 images in <a href="http://en.wikipedia.org/wiki/Apple_Icon_Image_format">Apple's ICNS format.</a> You can create such files easily in OS X or convert PNG files to ICNS format with <a href="http://icns.sourceforge.net/">libicns.</a></li>
+<li>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 <tt>CentOS</tt>, it matches the <tt>os_centos.icns</tt> icon. This match is performed on a word-by-word basis within the name, with "words" being delimited by spaces, dashes (<tt>-</tt>), and underscores (<tt>_</tt>). Thus, a volume called <tt>Debian-boot</tt> will match <tt>os_debian.icns</tt> or <tt>os_boot.icns</tt>.</li>
 
 <li>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 <tt>.VolumeIcon.icns</tt> 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.</li>
 
+<li>Certain boot loaders have hard-coded icons associated with them. For instance, filenames beginning with <tt>vmlinuz</tt> or <tt>bzImage</tt> acquire Linux "Tux" icons and the <tt>bootmgfw.efi</tt> 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.</li>
+
 </ul>
 
-<p>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.</p>
+<p>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.</p>
 
-<p>In addition to the main OS tag icon, you can set the <i>badge</i> icon for a volume by creating a file called <tt>.VolumeBadge.icns</tt> 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.</p>
+<p>In addition to the main OS tag icon, you can set the <i>badge</i> icon for a volume by creating a file called <tt>.VolumeBadge.icns</tt> 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 <tt>icons</tt> subdirectory (<tt>vol_external.icns</tt>, <tt>vol_internal.icns</tt>, and <tt>vol_optical.icns</tt>) with a completely transparent badge. The <tt>transparent.icns</tt> file in the rEFInd <tt>icons</tt> directory may be used for this purpose.</p>
 
 <h2>Adjusting the Global Configuration</h2>
 
@@ -145,8 +149,8 @@ timeout 20
 </tr>
 <tr>
    <td><tt>hideui</tt></td>
-   <td><tt>banner</tt>, <tt>label</tt>, <tt>singleuser</tt>, <tt>hwtest</tt>, <tt>arrows</tt>, or <tt>all</tt></td>
-   <td>Removes the specified user interface features. <tt>banner</tt> removes the banner graphic, <tt>label</tt> removes the text description of each tag and the countdown timer, <tt>singleuser</tt> removes the single-user option from the Mac OS sub-menu, <tt>hwtest</tt> removes the Mac OS hardware test option, <tt>arrows</tt> removes the arrows to the right or left of the OS tags when rEFInd finds too many OSes to display simultaneously, and <tt>all</tt> removes all of these options. You can specify multiple parameters with this option. The default is to set none of these values.</td>
+   <td><tt>banner</tt>, <tt>label</tt>, <tt>singleuser</tt>, <tt>hwtest</tt>, <tt>arrows</tt>, <tt>hints</tt>, <tt>editor</tt>, or <tt>all</tt></td>
+   <td>Removes the specified user interface features. <tt>banner</tt> removes the banner graphic, <tt>label</tt> removes the text description of each tag and the countdown timer, <tt>singleuser</tt> removes the single-user option from the Mac OS sub-menu, <tt>hwtest</tt> removes the Mac OS hardware test option, <tt>arrows</tt> removes the arrows to the right or left of the OS tags when rEFInd finds too many OSes to display simultaneously, <tt>hints</tt> removes the brief description of what basic keypressed do, <tt>editor</tt> disables the options editor, and <tt>all</tt> removes all of these options. You can specify multiple parameters with this option. The default is to set none of these values.</td>
 </tr>
 <tr>
    <td><tt>icons_dir</tt></td>
@@ -175,13 +179,18 @@ timeout 20
 </tr>
 <tr>
    <td><tt>textonly</tt></td>
-   <td>None</td>
-   <td>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.</td>
+   <td>None or <tt>0</tt></td>
+   <td>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 <tt>0</tt> causes text mode to be used; passing a <tt>0</tt> 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.)</td>
+</tr>
+<tr>
+   <td><tt>textmode</tt></td>
+   <td>text mode number</td>
+   <td>Sets the text-mode video resolution to be used in conjunction with <tt>textonly</tt> or for the line editor and program-launch screens. This option takes a single-digit code. Mode <tt>0</tt> is guaranteed to be present and should be 80x25. Mode <tt>1</tt> 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 <tt>textonly</tt> results in an incorrect graphics video mode being set. Pressing the Esc key corrects the problem.</td>
 </tr>
 <tr>
    <td><tt>resolution</tt></td>
-   <td>Two integer values</td>
-   <td>Sets the video resolution used by rEFInd; takes a width and a height as options. For instance, <tt>resolution 1024 768</tt> 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.<i>x</i> (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 <tt>0</tt> or if you pass anything but two numbers. (Note that passing a resolution with an <tt>x</tt>, as in <tt>1024x768</tt>, will be interpreted as <i>one</i> 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.</td>
+   <td>one or two integer values</td>
+   <td>Sets the video resolution used by rEFInd; takes <i>either</i> a width and a height <i>or</i> a single UEFI video mode number as options. For instance, <tt>resolution 1024 768</tt> sets the resolution to 1024x768. On UEFI systems, <tt>resolution 1</tt> 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.<i>x</i> (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 <tt>0</tt> or if you pass anything but two numbers. (Note that passing a resolution with an <tt>x</tt>, as in <tt>1024x768</tt>, will be interpreted as <i>one</i> 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.</td>
 </tr>
 <tr>
    <td><tt>use_graphics_for</tt></td>
@@ -200,13 +209,18 @@ timeout 20
 </tr>
 <tr>
    <td><tt>scan_delay</tt></td>
-   <td>Numeric (integer) value</td>
+   <td>numeric (integer) value</td>
    <td>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 <i>do</i> appear when you press the Esc key to re-scan, try uncommenting this option and setting it to a modest value, such as <tt>2</tt>, <tt>5</tt>, or even <tt>10</tt>. The default is <tt>0</tt>.</td>
 </tr>
 <tr>
    <td><tt>also_scan_dirs</tt></td>
    <td>directory path(s)</td>
-   <td>Adds the specified directory or directories to the directory list that rEFInd scans for EFI boot loaders when <tt>scanfor</tt> includes the <tt>internal</tt>, <tt>external</tt>, or <tt>optical</tt> options. Directories are specified relative to the filesystem's root directory. If this option is used, it's applied to <i>all</i> the filesystems that rEFInd scans. If a specified directory doesn't exist, rEFInd ignores it (no error results).</td>
+   <td>Adds the specified directory or directories to the directory list that rEFInd scans for EFI boot loaders when <tt>scanfor</tt> includes the <tt>internal</tt>, <tt>external</tt>, or <tt>optical</tt> options. Directories are specified relative to the filesystem's root directory. If this option is used, it's applied to <i>all</i> the filesystems that rEFInd scans. If a specified directory doesn't exist, rEFInd ignores it (no error results). The default value is <tt>boot</tt>, which is useful for locating Linux kernels when you have an EFI driver for your Linux root (<tt>/</tt>) filesystem.</td>
+</tr>
+<tr>
+   <td><tt>dont_scan_volumes</tt> or <tt>don't_scan_volumes</tt></td>
+   <td>filesystem label(s)</td>
+   <td>Adds the specified volume or volumes to a volume "blacklist"&mdash;these filesystems are <i>not</i> 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.</td>
 </tr>
 <tr>
    <td><tt>dont_scan_dirs</tt> or <tt>don't_scan_dirs</tt></td>
@@ -220,14 +234,19 @@ timeout 20
 </tr>
 <tr>
    <td><tt>scan_all_linux_kernels</tt></td>
-   <td>None</td>
-   <td>When set, causes rEFInd to add Linux kernels (files with names that begin with <tt>vmlinuz</tt> or <tt>bzImage</tt>) to the list of EFI boot loaders, even if they lack <tt>.efi</tt> 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 <tt>.efi</tt>. Of course, the kernels must still be stored on a filesystem that rEFInd can read, and in a directory that it scans. (<a href="drivers.html">Drivers</a> and the <tt>also_scan_dirs</tt> 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 <tt>refind.conf-sample</tt> 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.</td>
+   <td>None or <tt>0</tt></td>
+   <td>When set, causes rEFInd to add Linux kernels (files with names that begin with <tt>vmlinuz</tt> or <tt>bzImage</tt>) to the list of EFI boot loaders, even if they lack <tt>.efi</tt> 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 <tt>.efi</tt>. Of course, the kernels must still be stored on a filesystem that rEFInd can read, and in a directory that it scans. (<a href="drivers.html">Drivers</a> and the <tt>also_scan_dirs</tt> 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 <tt>refind.conf-sample</tt> 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 <tt>0</tt> causes scans for all kernels to occur; passing a <tt>0</tt> causes these kernels to not be scanned. (This could be useful if you want to override a setting of <tt>scan_all_linux_kernels</tt> in an included secondary configuration file.)</td>
 </tr>
 <tr>
    <td><tt>default_selection</tt></td>
    <td>A substring of a boot loader's title; or a numeric position</td>
    <td>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 <tt>default_selection</tt>, 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 <tt>default_selection</tt>, 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.</td>
 </tr>
+<tr>
+   <td><tt>include</tt></td>
+   <td>filename</td>
+   <td>Includes the specified file into the current configuration file. Essentially, the included file replaces the <tt>include</tt> 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.</td>
+</tr>
 </table>
 
 <p>Prior to version 0.2.4, rEFInd supported a token called <tt>disable</tt>, whose function partially overlapped with <tt>hideui</tt>. Version 0.2.4 merges many of the features of these two tokens into <tt>hideui</tt> and creates the new <tt>showtools</tt> option, which provides the remaining functionality in a more flexible way.</p>
index fb5852f1313e431e10bd2980bab1e7f189a45e7c..a881ff20857da37afdf12566588b1c2d6df8a819 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 4/19/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
@@ -136,6 +136,21 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
     used in the same way as the ReiserFS driver. Although it's called an
     "ext2fs" driver, it also works with ext3fs.</li>
 
+<li><b>Ext4fs</b>&mdash;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 <tt>meta_bg</tt> 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 <tt
+    class="userinput">dumpe2fs <i>/dev/sda2</i> | grep features</tt>,
+    changing <tt class="userinput"><i>/dev/sda2</i></tt> to your
+    filesystem's device.</li>
+
 <li><b>ISO-9660</b>&mdash;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</a></p>
 
 <p>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 <a href="#notes">"Notes on Specific Drivers;"</a> however, these problems are very minor on most systems.</p>
 
-<p class="sidebar"><b>Note:</b> rEFInd's <tt>install.sh</tt> script does not install drivers by default. It does if you pass it the <tt>--drivers</tt> option, though. If you installed manually, you may also have installed rEFInd's drivers. See the <a href="installing.html">Installing rEFInd</a> page for details.</p>
+<p class="sidebar"><b>Note:</b> rEFInd's <tt>install.sh</tt> script does not install drivers by default on OS X, but on Linux, it installs the driver required to read the <tt>/boot</tt> directory, if one is available. The script installs all the available drivers if you pass it the <tt>--drivers</tt> option. See the <a href="installing.html">Installing rEFInd</a> page for details.</p>
 
 <p>If you want to use one or more of these drivers, you can install them from the rEFInd binary package from the <tt>refind/drivers_<tt class="variable">arch</tt></tt> directory, where <tt class="variable">arch</tt> is a CPU architecture code&mdash;<tt>x64</tt> or <tt>ia32</tt>. The files are named after the filesystems they handle, such as <tt>ext2_x64.efi</tt> for the 64-bit ext2fs driver. You should copy the files for the filesystems you want to use to the <tt>drivers</tt> or <tt>drivers_<tt class="variable">arch</tt></tt> 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.</p>
 
@@ -203,13 +218,13 @@ fs0: <tt class="userinput">map -r</tt>
 <h2>Notes on Specific Drivers</h2>
 </a>
 
-<p>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&mdash;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 <tt>/boot</tt> partition; however, if you're willing to use ext3fs or ReiserFS on your root (<tt>/</tt>) 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.</p>
+<p>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&mdash;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 <tt>/boot</tt> partition; however, if you're willing to use ext3fs, ext4fs, or ReiserFS on your root (<tt>/</tt>) 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.</p>
 
-<p>The Pfisterer ext2fs and ReiserFS drivers work, but they are a bit sluggish&mdash;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&mdash;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&ndash;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 <tt>/boot</tt> 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 <tt>/etc/fstab</tt> entry for a new UUID value, though. As noted earlier, be sure to use <tt>notail</tt> as an option in <tt>/etc/fstab</tt> for ReiserFS if you want to read it from EFI.) You can even use HFS+ on a Linux <tt>/boot</tt> 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 <tt>/boot</tt> partition and not deal with drivers at all. Mounting your ESP at <tt>/boot</tt> is a practical solution for many users.</p>
+<p>The Pfisterer ReiserFS and ext2fs drivers work, but they are a bit sluggish&mdash;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&mdash;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&ndash;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 <tt>/boot</tt> 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 <tt>/etc/fstab</tt> entry for a new UUID value, though. As noted earlier, be sure to use <tt>notail</tt> as an option in <tt>/etc/fstab</tt> for ReiserFS if you want to read it from EFI.) You can even use HFS+ on a Linux <tt>/boot</tt> 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 <tt>/boot</tt> partition and not deal with drivers at all. Mounting your ESP at <tt>/boot</tt> is a practical solution for many users.</p>
 
 <p>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.</p>
 
-<p>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 <i>relative</i> links, as in <tt>../otherdist/bzImage.efi</tt>, at least if the partition is not Linux's root filesystem.)</p>
+<p>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 <i>relative</i> links, as in <tt>../otherdist/bzImage.efi</tt>, at least if the partition is not Linux's root filesystem.)</p>
 
 </ul>
 
index b9f41c31cff018663c95e871747d87bdab562247..086c889b238ffc03c2e0cf9fad20dbb89e960b2c 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 <p>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!</p>
 
@@ -111,7 +111,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <li>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.)</li>
+    0.4.0.)</li>
 
 </ul>
 
@@ -143,7 +143,7 @@ lack a usable CSM.</li>
 
 <li>The ability to specify additional directories to scan for boot loaders and drivers (as of version 0.2.7).</li>
 
-<li>The ability to specify directories to <i>not</i> be scanned for boot loaders, even if they would ordinarily be scanned (as of version 0.4.2).</li>
+<li>The ability to specify volumes and directories to <i>not</i> 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).</li>
 
 <li>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).</li>
 
@@ -151,7 +151,7 @@ lack a usable CSM.</li>
 
 <li>The ability to specify an additional icon storage directory, to assist in efforts to customize rEFInd's appearance (as of version 0.3.4).</li>
 
-<li>The ability to set the screen's resolution, within limits imposed by the EFI (as of rEFInd 0.3.0).</li>
+<li>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.</li>
 
 <li>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.)</li>
 
@@ -167,9 +167,9 @@ lack a usable CSM.</li>
 
 <li>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.)</li>
 
-<li>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.)</li>
+<li>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.)</li>
 
-<li>Beginning with version 0.5.0, the ability to "talk" to the <a href="http://mjg59.dreamwidth.org/20303.html">shim boot loader</a> 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.</li>
+<li>Beginning with version 0.5.0, the ability to "talk" to the <a href="http://mjg59.dreamwidth.org/20303.html">shim boot loader</a> 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.</li>
 
 </ul>
 
index 3da81eec34d12bcf521e6c3287333cbada9657a9..4d8132923f0adc46b1c61818f72bad4527960714 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/18/2012, referencing rEFInd 0.6.0</p>
 
 <p>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!</p>
 
@@ -98,7 +98,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 <ul>
 
 <li><b><a
-    href="http://sourceforge.net/projects/refind/files/0.5.0/refind-src-0.5.0.zip/download">A
+    href="http://sourceforge.net/projects/refind/files/0.6.0/refind-src-0.6.0.zip/download">A
     source code zip file</a></b>&mdash;This is useful if you want to
     compile the software locally. Note that I use Linux with the <a
     href="https://sourceforge.net/projects/tianocore/">TianoCore EFI
@@ -109,7 +109,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
     possible, but I've not attempted it.</li>
 
 <li><b><a
-    href="http://sourceforge.net/projects/refind/files/0.5.0/refind-bin-0.5.0.zip/download">A
+    href="http://sourceforge.net/projects/refind/files/0.6.0/refind-bin-0.6.0.zip/download">A
     binary zip file</a></b>&mdash;Download this if you want to install
     rEFInd and/or its filesystem drivers on an <i>x</i>86 or <i>x</i>86-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</a></p>
     either build.)</li>
 -->
 
-<p class="sidebar"><b>Tip:</b> If you want a bootable USB flash drive, download the binary zip file or CD-R image file, prepare a USB flash drive with a FAT32 ESP, and then use the <tt>install.sh</tt> program's <tt>--usedefault</tt> option, as in <tt class="userinput">bash install.sh --usedefault /dev/sdd1</tt> to install to the first partition on <tt>/dev/sdd</tt>. This procedure should work even on a BIOS-booted computer.</p>
+<p class="sidebar"><b>Tip:</b> If you want a bootable USB flash drive, download the binary zip file or CD-R image file, prepare a USB flash drive with a FAT32 ESP, and then use the <tt>install.sh</tt> program's <tt>--usedefault</tt> option, and perhaps the <tt>--alldrivers</tt> option, as in <tt class="userinput">bash install.sh --usedefault /dev/sdd1 --alldrivers</tt> to install to the first partition on <tt>/dev/sdd</tt>. This procedure should work even on a BIOS-booted computer.</p>
 
 <li><b><a
-    href="http://sourceforge.net/projects/refind/files/0.5.0/refind-cd-0.5.0.zip/download">A
+    href="http://sourceforge.net/projects/refind/files/0.6.0/refind-cd-0.6.0.zip/download">A
     CD-R image file</a></b>&mdash;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
index bef175ad9f732f3e1cb4dd42e2a8b2cd42896414..bcebfbba76a4e36d678e98c57116a7c65f023bc4 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
index 40c5f87cee13e369b9764c84f4189976137ab5ed..03f54ccf308e61dde63e4719d48d93388833518d 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
@@ -92,7 +92,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p class="sidebar"><b>Important:</b> A rEFInd zip file, when uncompressed, creates a directory called <tt>refind-<i>version</i></tt>, where <tt><i>version</i></tt> is the version number. This directory includes a subdirectory called <tt>refind</tt> that holds the boot loader, along with another that holds documentation, as well as miscellaneous files in <tt>refind-<i>version</i></tt> itself. When I refer to "the <tt>refind</tt> directory" on this page, I mean the directory with that precise name, not the <tt>refind-<i>version</i></tt> directory that is its parent.</p>
 
-<p>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, <a href="#installsh"><tt>install.sh</tt>,</a> which provides easy one-command installation on most systems. Occasionally this script will fail, though, so I also provide explicit instructions for <a href="#linux">Linux</a> and <a href="#osx">Mac OS X.</a> Installation under <a href="#windows">Windows</a> also must be done manually. In some cases, you'll have to deviate from the default naming conventions, as described in <a href="#naming">a section on this topic.</a> If you're upgrading rEFInd, see the <a href="#upgrading">section on upgrading.</a> Finally, I describe how to install some <a href="#addons">additional components</a> you might find useful.</a> 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 <a href="drivers.html">page on using drivers with rEFInd.</a></p>
+<p>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, <a href="#installsh"><tt>install.sh</tt>,</a> which provides easy one-command installation on most systems. Occasionally this script will fail, though, so I also provide explicit instructions for <a href="#linux">Linux</a> and <a href="#osx">Mac OS X.</a> Installation under <a href="#windows">Windows</a> also must be done manually. In some cases, you'll have to deviate from the default naming conventions, as described in <a href="#naming">a section on this topic.</a> If you're upgrading rEFInd, see the <a href="#upgrading">section on upgrading.</a> Finally, I describe how to install some <a href="#addons">additional components</a> you might find useful.</a></p>
 
 <a name="installsh">
 <h2>Installing rEFInd Using <tt>install.sh</tt> under Linux or Mac OS X</h2>
@@ -195,13 +195,37 @@ Installation has completed successfully.</pre>
     though; because of the popularity of dual boots with Windows on Macs,
     the BIOS/legacy scans are enabled by default on Macs.</li>
 
+<li>On Linux, <tt>install.sh</tt> checks the filesystem type of the
+    <tt>/boot</tt> directory and, if a matching filesystem driver is
+    available, installs it. Note that the "<tt>/boot</tt> directory" may be
+    on a separate partition or it may be part of your root (<tt>/</tt>)
+    filesystem, in which case the driver for your root filesystem is
+    installed. If <tt>install.sh</tt> 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 <tt>/boot</tt> partition and if you mount that partition at
+    <tt>/boot</tt> in your emergency system, and the ESP at
+    <tt>/boot/efi</tt>.</li>
+
+<li>If you run <tt>install.sh</tt> on Linux and if
+    <tt>/boot/refind_linux.conf</tt> doesn't already exist,
+    <tt>install.sh</tt> creates this file and populates it with a few
+    sample entries. If <tt>/boot</tt> 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
+    <tt>refind_linux.conf</tt>, though&mdash;for instance, to add
+    <tt>dolvm</tt> to the boot options on Gentoo systems that use LVM.</li>
+
 </ul>
 
 <p>In addition to these quirks, you should be aware of some options that <tt>install.sh</tt> supports to enable you to customize your installation in various ways. The syntax for <tt>install.sh</tt> is as follows:</p>
 
 <pre class="listing">
-install.sh [--esp | --usedefault <tt class="variable">device-file</tt>] [--drivers] [--shim <tt class="variable">shim-filename</tt>] \
-           [--localkeys]
+install.sh [--esp | --usedefault <tt class="variable">device-file</tt>] [--nodrivers | --alldrivers] \
+           [--shim <tt class="variable">shim-filename</tt>] [--localkeys]
 </pre>
 
 <p>The details of the options are summarized in <a href="#table1">Table 1.</a> Using some of these options in unusual conditions can generate warnings and prompts to confirm your actions. In particular, using <tt>--shim</tt> or <tt>--localkeys</tt> when you're <i>not</i> booted in Secure Boot mode, or failing to use <tt>--shim</tt> when you <i>are</i> booted in Secure Boot mode, will generate a query and a request to confirm your installation. Consult the <a href="secureboot.html">Managing Secure Boot</a> page for more on this topic.</p>
@@ -220,8 +244,12 @@ install.sh [--esp | --usedefault <tt class="variable">device-file</tt>] [--drive
    <td>You can install rEFInd to a disk using the default/fallback filename of <tt>EFI/BOOT/bootx64.efi</tt> (and <tt>EFI/BOOT/bootia32.efi</tt>, if the 32-bit build is available) using this option. The <tt class="variable">device-file</tt> should be an <i>unmounted</i> ESP, or at least a FAT partition, as in <tt>--usedefault /dev/sdc1</tt>. Your computer's NVRAM entries will <i>not</i> 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 <tt>--esp</tt>.</td>
 </tr>
 <tr>
-   <td><tt>--drivers</tt></td>
-   <td>Ordinarily <tt>install.sh</tt> 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.</td>
+   <td><tt>--nodrivers</tt></td>
+   <td>Ordinarily <tt>install.sh</tt> attempts to install the driver required to read <tt>/boot</tt> 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 <tt>--nodrivers</tt> option. This option is the default on OS X or when you use <tt>--usedefault</tt>.</td>
+</tr>
+<tr>
+   <td><tt>--alldrivers</tt></td>
+   <td>When you specify this option, <tt>install.sh</tt> copies <i>all</i> 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.</td>
 </tr>
 <tr>
    <td><tt>--shim <tt class="variable">shim-filename</tt></tt></td>
@@ -261,7 +289,7 @@ Filesystem     1K-blocks  Used Available Use% Mounted on
 
 <li>Type <tt><b>rm refind_ia32.efi</b></tt> to remove the IA32 binary if you're using an <i>x</i>86-64 (64-bit) system; or type <tt><b>rm refind_x64.efi</b></tt> to remove the <i>x</i>86-64 binary if you're using an <i>x</i>86 (32-bit) system. You can optionally rename the binary you keep as <tt>refind.efi</tt>, 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 <tt>refind_x64.efi</tt>.</li>
 
-<li>Optionally, type <tt class="userinput">rm -r drivers_ia32</tt> to remove the <i>x</i>86 drivers from an <i>x</i>86-64 system, or <tt class="userinput">rm -r drivers_x64</tt> to remove the <i>x</i>86-64 drivers from a 32-bit <i>x</i>86 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 <a href="drivers.html">page on drivers</a> for more on this topic.</li>
+<li>Optionally, type <tt class="userinput">rm -r drivers_ia32</tt> to remove the <i>x</i>86 drivers from an <i>x</i>86-64 system, or <tt class="userinput">rm -r drivers_x64</tt> to remove the <i>x</i>86-64 drivers from a 32-bit <i>x</i>86 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 <a href="drivers.html">page on drivers</a> for more on this topic.</li>
 
 <li>Rename the configuration file by typing <tt><b>mv refind.conf-sample refind.conf</b></tt>. Consult the <a href="configfile.html">Editing the rEFInd Configuration File</a> page for information on how to adjust your options.</li>
 
@@ -516,7 +544,7 @@ $ <b>ioreg -l -p IODeviceTree | grep firmware-abi</b>
 <li><b>Drivers</b>&mdash;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
     <a href="drivers.html">Using EFI Drivers</a> page for more on this
@@ -550,6 +578,8 @@ $ <b>ioreg -l -p IODeviceTree | grep firmware-abi</b>
 
 </ol>
 
+<p>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.</p>
+
 <a name="uninstalling">
 <h2>Uninstalling rEFInd</h2>
 </a>
index 77cabc0e1a1d03c1d17790d983f48b20000eed19..5e9aa882f05c3e8e4a3f70057337833658a7501b 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/19/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
@@ -92,17 +92,160 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>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.</p>
 
-<p>Under Linux, by contrast, things can get complicated. As detailed on my <a href="http://www.rodsbooks.com/efi-bootloaders/index.html">Managing EFI Boot Loaders for Linux</a> 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.</p>
+<p>Under Linux, by contrast, things can get complicated. As detailed on my <a href="http://www.rodsbooks.com/efi-bootloaders/index.html">Managing EFI Boot Loaders for Linux</a> 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 <a href="#traditional">traditional Linux boot loaders.</a> It works even better with the Linux EFI stub loader, so I provide <a href="#quickstart">instructions on starting with it.</a> For those interested in manual configuration, I also provide <a href="#efistub">detailed instructions</a> on how the EFI stub support works and how to configure it.</p>
 
+<a name="traditional">
 <h2>Using a Traditional Linux Boot Loader</h2>
+</a>
 
-<p>I consider <a href="http://www.rodsbooks.com/efi-bootloaders/elilo.html">ELILO,</a> <a href="http://www.rodsbooks.com/efi-bootloaders/grub_legacy.html">GRUB Legacy,</a> and <a href="http://www.rodsbooks.com/efi-bootloaders/grub2.html">GRUB 2</a> 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).</p>
+<p>I consider <a href="http://www.rodsbooks.com/efi-bootloaders/elilo.html">ELILO,</a> <a href="http://www.rodsbooks.com/efi-bootloaders/grub_legacy.html">GRUB Legacy,</a> and <a href="http://www.rodsbooks.com/efi-bootloaders/grub2.html">GRUB 2</a> 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).</p>
 
 <p>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.</p>
 
 <p>If you prefer, you can disable automatic scanning and create an entry in <tt>refind.conf</tt> for your distribution, as described on the <a href="configfile.html">Configuring the Boot Manager</a> page. This method is harder to set up but can be preferable if you want to customize your options.</p>
 
-<h2>Using the EFI Stub Loader</h2>
+<a name="quickstart">
+<h2>Using the EFI Stub Loader: A Quick Setup Guide</h2>
+</a>
+
+<p>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 <a href="#easiest">easiest method</a> for those with compatible partition and filesystem layouts, a <a href="#testing">quick test configuration</a> for those without such a layout, and <a href="#longterm">a long-term setup</a> for those without the ideal setup.</p>
+
+<a name="easiest">
+<h3>For Those With Foresight or Luck: The Easiest Method</h3>
+</a>
+
+<p>This method requires that your <tt>/boot</tt> directory, whether it's on a separate partition or is a regular directory in your root (<tt>/</tt>) filesystem, be readable by the EFI. At the moment, all EFI implementations can read FAT and Macs can read HFS+. By using <a href="drivers.html">drivers,</a> 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 <tt>/boot</tt>, 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 <tt>/boot</tt> partition. You must also have a 3.3.0 or later Linux kernel with EFI stub support, of course.</p>
+
+<p>If you installed rEFInd 0.6.0 or later with its <tt>install.sh</tt> 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:
+
+<ol>
+
+<li>Copy the relevant driver file for your filesystem and architecture to
+    the <tt>drivers</tt> or <tt>drivers_<tt class="variable">arch</tt></tt>
+    subdirectory of the rEFInd installation directory on the ESP. You may
+    need to create this subdirectory, too.</li>
+
+<li>Create a <tt>refind_linux.conf</tt> file in your <tt>/boot</tt>
+    directory. The <tt>mkrlconf.sh</tt> script that comes with rEFInd
+    should do this job, or you can do it manually as described <a
+    href="#efistub">later.</a></li>
+
+</ol>
+
+<p>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 <a href="#longterm">maintenance-free setup</a> section. If you have problems, you may need to adjust the <tt>refind_linux.conf</tt> file, as described in the <a href="#efistub">detailed configuration section.</a></p>
+
+<a name="testing">
+<h3>Testing the EFI Stub Loader</h3>
+</a>
+
+<p>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:</p>
+
+<ol>
+
+<li>Copy your kernel file (<tt>vmlinuz-*</tt>) and matching initial RAM
+    disk file (<tt>init*</tt>) from <tt>/boot</tt> to a subdirectory of
+    <tt>EFI</tt> on your ESP. Your distribution's directory there should
+    work fine. For instance, typing <tt class="userinput">cp
+    /boot/vmlinuz-3.6.7-4.fc17.x86_64
+    /boot/initramfs-3.6.7-4.fc17.x86_64.img /boot/efi/EFI/redhat</tt> 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.</li>
+
+<li>Copy the <tt>/boot/refind_linux.conf</tt> file to the same directory to
+    which you copied your kernel. If this file doesn't exist, create it by
+    running (as <tt>root</tt>) the <tt>mkrlconf.sh</tt> script that came
+    with rEFInd.</li>
+
+<li>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 <tt>refind_linux.conf</tt> file. See the <a
+    href="#efistub">detailed configuration section</a> 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 <tt>root=</tt>
+    option in <tt>refind_linux.conf</tt>.</li>
+
+</ol>
+
+<p>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 <tt>/boot</tt> directory, where most Linux distributions place their kernels.</p>
+
+<a name="longterm">
+<h3>Configuring a Maintenance-Free Setup</h3>
+</a>
+
+<p>If your <tt>/boot</tt> 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 <a href="#easiest">easiest solution.</a> 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 <tt>root</tt>, or precede each of these commands with <tt>sudo</tt>:</p>
+
+<ol>
+
+<li>Begin with your ESP mounted at <tt>/boot/efi</tt>, which is the most
+    common location. If it's not mounted there, type <tt
+    class="userinput">mount /dev/sda1 /boot/efi</tt> to do so (adjusting
+    <tt>/dev/sda1</tt>, if necessary), or mount it elsewhere and adjust the
+    paths in the following procedure as necessary.</li>
+
+<li>Check the size of the ESP by typing <tt class="userinput">df -h
+    /boot/efi</tt>. The ESP must be large enough to hold several Linux
+    kernels and initial RAM disk files&mdash;100MiB at a bare minimum, and
+    preferably 200&ndash;500MiB.</li>
+
+<li>Check your <tt>/boot</tt> 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.</li>
+
+<li>Type <tt class="userinput">cp -r /boot/* /boot/efi</tt>. You'll see an
+    error message about being unable to copy <tt>/boot/efi</tt> into
+    itself. Ignore this.</li>
+
+<li>Type <tt class="userinput">umount /boot/efi</tt>.</li>
+
+<li>Edit <tt>/etc/fstab</tt> and change the mount point for
+    <tt>/boot/efi</tt> to <tt>/boot</tt>. If the ESP isn't present in
+    <tt>/etc/fstab</tt>, you must create an entry for it, with a mount
+    point of <tt>/boot</tt>.</li>
+
+<li>Type <tt class="userinput">mount -a</tt> to re-mount everything,
+    including <tt>/boot</tt>. Check that your normal <tt>/boot</tt> files
+    are all present, along with the new <tt>/boot/EFI</tt> directory, which
+    holds what used to be <tt>/boot/efi/EFI</tt>. If something seems to be
+    missing (other than <tt>/boot/efi</tt> with a lowercase <tt>efi</tt>),
+    then you should try to correct the problem.</li>
+
+<li>If it doesn't already exist, create a file called
+    <tt>/boot/refind_linux.conf</tt> and populate it with kernel options,
+    as described <a href="#refind_linux">later.</a> If this file doesn't
+    already exist, the easiest way to create it is to run the
+    <tt>mkrlconf.sh</tt> script that comes with rEFInd 0.5.1 and
+    later.</li>
+
+<li>Check your <tt>refind.conf</tt> file (presumably in
+    <tt>/boot/EFI/refind</tt>) to be sure that the
+    <tt>scan_all_linux_kernels</tt> line is uncommented. If it's not,
+    uncomment that line.</li>
+
+<li>Optionally, type <tt class="userinput">cp
+    /boot/EFI/refind/icons/os_<i>name</i>.icns /boot/.VolumeIcon.icns</tt>
+    to give loaders in <tt>/boot</tt> an icon for your distribution.</li>
+
+<li>Reboot to test that this configuration works.</li>
+
+</ol>
+
+<p>Recall that in step #4, you <i>copied</i> the contents of <tt>/boot</tt> (as a safety measure), but you did not move them. Therefore, you ended up with two copies of your kernels and other <tt>/boot</tt> directory contents, with one copy hiding the other when you mounted the ESP at <tt>/boot</tt>. Once you've booted successfully and are sure all is working well, you can recover some disk space by unmounting <tt>/boot</tt> and deleting the contents of the underlying <tt>/boot</tt> directory on your root (<tt>/</tt>) filesystem. Be sure that the <tt>/boot</tt> partition is unmounted before you do this, though! Also, be sure to leave the <tt>/boot</tt> directory itself in place, even if it has no contents; the directory is needed as a mount point for the <tt>/boot</tt> partition. Note that GRUB 2 may stop working if you delete its files from the root filesystem's <tt>/boot/grub</tt> directory, so if you want to keep GRUB around, you should re-install it with the separate <tt>/boot</tt> partition mounted.</p>
+
+<p>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.</p>
+
+<p>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 <tt>/boot</tt> 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&ndash;500MiB). Mount your new <tt>/boot</tt> partition at a temporary location, copy or move the current <tt>/boot</tt> files into it, unmount it, and add it to <tt>/etc/fstab</tt> as <tt>/boot</tt>.</p>
+
+<p>If your distribution already uses a separate <tt>/boot</tt> 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 <tt>/etc/fstab</tt> to ensure that the computer mounts the new filesystem when you boot. If you use a separate non-ESP <tt>/boot</tt> partition, you'll probably want to continue mounting the ESP at <tt>/boot/efi</tt>.</p>
+
+<a name="efistub">
+<h2>EFI Stub Loader Support Technical Details</h2>
+</a>
 
 <p>The Linux <a href="http://www.rodsbooks.com/efi-bootloaders/efistub.html">EFI stub loader</a> 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 (<tt>/</tt>) 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.</p>
 
@@ -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.</p>
+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.</p>
 
 <p>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:</p>
 
@@ -131,9 +274,10 @@ another possibility.</p>
     with version 0.3.0, if you uncomment the
     <tt>scan_all_linux_kernels</tt> option in <tt>refind.conf</tt>, rEFInd
     will also scan for kernels <i>without</i> a <tt>.efi</tt> 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.</li>
+    extension. This option is uncommented by default, but if you comment it
+    out, delete it, or change it to read <tt>scan_all_linux_kernels 0</tt>,
+    rEFInd won't scan for kernels that lack <tt>.efi</tt> filename
+    extensions.</li>
 
 <p class="sidebar">A kernel whose filename lacks a version string matches an initial RAM disk that also lacks a version string in its filename. Note that you can reliably use only <i>one</i> kernel and initial RAM disk per directory that lack version numbers in their filenames.</p>
 
@@ -157,12 +301,16 @@ another possibility.</p>
     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.</li>
+    options that are accessible from the main menu tag's submenu screen. If
+    you installed rEFInd 0.5.1 or later with the <tt>install.sh</tt>
+    script, that script created a sample <tt>refind_linux.conf</tt> file,
+    customized for your computer, in <tt>/boot</tt>. This file will work
+    without changes on many installations, but you may need to tweak it for
+    some.</li>
 
 </ol>
 
-<p>The intent of this system is that distribution maintainers can place their kernels, initial RAM disks, and a <tt>refind_linux.conf</tt> 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 <tt>refind_linux.conf</tt> 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.</p>
+<p>The intent of this system is that distribution maintainers can place their kernels, initial RAM disks, and a <tt>refind_linux.conf</tt> file in their own subdirectories on the ESP, on EFI-accessible <tt>/boot</tt> partitions, or in <tt>/boot</tt> directories on EFI-accessible Linux root (<tt>/</tt>) 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 <tt>refind_linux.conf</tt> 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.</p>
 
 <p>The <tt>scan_all_linux_kernels</tt> 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 <tt>/boot</tt> partition. In these cases, if all the kernels in Linux's <tt>/boot</tt> 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 <tt>refind_linux.conf</tt> file and you may need to install a driver or set the <tt>also_scan_dirs</tt> option in <tt>refind.conf</tt>; but these are one-time requirements. Set up in this way, ongoing maintenance to handle kernel updates drops to zero!</p>
 
@@ -179,12 +327,14 @@ total 17943
 
 <p>When rEFInd scans this directory, it will find two EFI boot loaders in <tt>EFI/ubuntu</tt>: <tt>grubx64.EFI</tt> and <tt>bzImage-3.3.0.efi</tt>. 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 <tt>refind_linux.conf</tt> file contains a list of labels and options:</p>
 
+<a name="refind_linux">
 <pre class="listing">
-"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"
 </pre>
+</a>
 
 <p>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 <tt>"root=/dev/sdb9 my_opt=""this is it"""</tt>, which passes <tt>root=/dev/sdb9 my_opt="this is it"</tt> 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 (<tt>#</tt>), as in the fourth line in this example.</p>
 
@@ -195,7 +345,7 @@ total 17943
     a refind_linux.conf file in the Linux kernel's directory."
     border=2></center><br />
 
-<p>Note that the first entry shown here takes a name that's set in rEFInd rather than the one specified in the <tt>refind_linux.conf</tt> file. The remaining names match those specified in the file, though.</p>
+<p>To assist in initial configuration, rEFInd's <tt>install.sh</tt> script creates a sample <tt>refind_linux.conf</tt> file in <tt>/boot</tt>. This sample file defines three entries, the first two of which use the default GRUB options defined in <tt>/etc/default/grub</tt> 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 <tt>mkrlconf.sh</tt> script that comes with rEFInd. If you pass it the <tt>--force</tt> option, it will overwrite the existing <tt>/boot/refind_linux.conf</tt> file; otherwise it will create the file only if one doesn't already exist.</p>
 
 <p>From a user's perspective, the submenus defined in this way work just like submenus defined via the <tt>submenuentry</tt> options in <tt>refind.conf</tt>, 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:</p>
 
index 7ccd1c0a3a7f65cb588c0c006aa3fc915d3d868a..7e1c7752c5fde864249e15ea4446bcab439dc8b9 100644 (file)
@@ -14,8 +14,7 @@
 <p class="subhead">by Roderick W. Smith, <a
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
-<p>Last Web page update: 12/6/2012</p>
-
+<p>Last Web page update: 12/16/2012</p>
 
 <p>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!</p>
 
@@ -93,7 +92,13 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <ul>
 
-<li><b>0.5.0 (12/5/2012)</b>&mdash;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 <a href="secureboot.html">Managing Secure Boot</a> page for details. Beyond this major new feature, this version includes several more minor improvements. These include a change to the <tt>resolution</tt> 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 <tt>dont_scan_files</tt> option to blacklist boot programs by filename; support for launching MokManager and Apple's Recovery HD partitions via tools (2nd-row) icons; new <tt>--usedefault</tt> and <tt>--drivers</tt> options to the <tt>install.sh</tt> script; a change of the <tt>esp</tt> installation script option to <tt>--esp</tt>; and the ability to use quote marks inside option strings by doubling them up.</li>
+<li><b>0.6.0 (12/16/2012)</b>&mdash;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 <tt>install.sh</tt> 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 <tt>install.sh</tt>, the addition of hint text to the rEFInd main menu, the ability to disable the options editor via the <tt>editor</tt> option to <tt>hideui</tt> in <tt>refind.conf</tt>, a new <tt>textmode</tt> option to <tt>refind.conf</tt> 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 <tt>refind_linux.conf</tt>), it will take precedence, and assorted obscure bug fixes. The <tt>NEWS.txt</tt> file goes into more details about many of these changes, as do the relevant pages of this HTML documentation.</li>
+
+<li><b>0.5.1.1 (12/12/2012)</b>&mdash;This is a micro-update to fix a bug in the <tt>install.sh</tt> script that prevented it from working under OS X. Aside from that, and a few small documentation changes, this version changes nothing in rEFInd.</li>
+
+<li><b>0.5.1 (12/11/2012)</b>&mdash;The most important changes to this version are to the <tt>install.sh</tt> script. It now supports two options, <tt>--shim</tt> and <tt>--localkeys</tt>, to aid in installation on a Secure Boot system. See the <a href="installing.html">Installing rEFInd</a> and <a href="secureboot.html">Managing Secure Boot</a> pages for details. The script also now creates a sample <tt>/boot/refind_linux.conf</tt> file to assist in setting up boots via the Linux EFI stub loader. All of these <tt>install.sh</tt> improvements work only in Linux. A separate <tt>mkrlconf.sh</tt> script creates a <tt>/boot/refind_linux.conf</tt> 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 <tt>include</tt> token to <tt>refind.conf</tt>, 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).</li>
+
+<li><b>0.5.0 (12/6/2012)</b>&mdash;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 <a href="secureboot.html">Managing Secure Boot</a> page for details. Beyond this major new feature, this version includes several more minor improvements. These include a change to the <tt>resolution</tt> 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 <tt>dont_scan_files</tt> option to blacklist boot programs by filename; support for launching MokManager and Apple's Recovery HD partitions via tools (2nd-row) icons; new <tt>--usedefault</tt> and <tt>--drivers</tt> options to the <tt>install.sh</tt> script; a change of the <tt>esp</tt> installation script option to <tt>--esp</tt>; and the ability to use quote marks inside option strings by doubling them up.</li>
 
 <li><b>0.4.7 (11/6/2012)</b>&mdash;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 <a href="http://freedesktop.org/wiki/Software/gummiboot">gummiboot,</a> which is another EFI boot manager. This version also alters the behavior of the <tt>scan_delay</tt> 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.</li>
 
index 7a5dc9763d08229d2e26d04876a9a70cfb483d07..930296fbb7eb26597cd088a794ff0ad8487721f0 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 11/13/2012; last Web page update:
-12/8/2012, referencing rEFInd 0.5.0.1</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
@@ -232,7 +232,7 @@ described on this page currently supports only <i>x</i>86-64, not
 
 <p>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 <i>About rEFInd</i> tool in the main menu. Check the <i>Platform</i> 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 <tt>showtools</tt> in <tt>refind.conf</tt>, you must be sure to include <tt>mok_tool</tt> as an option in order to gain access to it.)</p>
 
-<p>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.</p>
+<p>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 <a href="http://archive.ubuntu.com/ubuntu/pool/main/s/shim/shim_0~20120906.bcd0a4e8-0ubuntu4.debian.tar.gz">shim_0~20120906.bcd0a4e8-0ubuntu4.debian.tar.gz</a> tarball, as <tt>canonical-uefi-ca.der</tt>. (The filename extensions <tt>.cer</tt> and <tt>.der</tt> are interchangeable for most purposes.) I've also included this key with rEFInd, in the <tt>refind/keys</tt> subdirectory of its package file. To use this key, copy it to your ESP and enroll it with MokManager. See <a href="http://falstaff.agner.ch/2012/12/12/secure-boot-implementation-of-ubuntu-12-10-quantal-quetzal/">this blog post</a> 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.</p>
 
 <a name="mok">
 <h2>Managing Your MOKs</h2>
index 884401b4530b0e7c99d896d2fe4fa0ed20936e5d..3e370a173ddd566b9ee9c5d984d1926f0dd2346a 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 4/19/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
index 2fc86a5e93320f47091a694c5322d6c7484a2b52..d890e43446ad2466312a5cf6baa48759a0f82be4 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
@@ -165,6 +165,13 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
        from the partition data is harder than extracting the volume's
        label or counting up the filesystem numbers.</li>
 
+    <li>Currently, if a filesystem's label comes up empty, rEFInd
+       substitutes the size, so you get displays like <tt>boot
+       EFI\foo\bar.efi from 90 GiB volume</tt>. I'd like to add more
+       checks to substitute the GPT <i>partition</i> label if the
+       <i>filesystem</i> label comes up empty, or add a filesystem type
+       identifier to the size.</li>
+
     <li>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</a></p>
        <tt>/usr/local/UDK2010/MyWorkSpace/MdeModulePkg/Core/Dxe/Image/Image.c</tt>
        for the reference UEFI implementation. --> </li>
 
-    <li>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.</li>
-
     <li>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</a></p>
 
     <ul>
 
-    <li>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 <a
-       href="http://mjg59.dreamwidth.org/18945.html">Shim</a>
-       pre-bootloader to help handle signing and authentication. I need to
-       research the technical details more, though.</li>
-
     <li>EFI supports network boots. rEFInd doesn't, but it would be nice if
        it would.</li>
 
@@ -313,9 +308,6 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
        boot. Perhaps this could be done via a separate tool that could be
        launched much like the shell or <tt>gptsync</tt>.</li>
 
-    <li>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.</li>
-
     <li>A way to set the color of the font would be useful for theming
         purposes.</li>
 
@@ -327,20 +319,15 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
        written in a cross-platform GUI toolkit, so that a single code base
        can be used on any of the major OSes.</li>
 
-    <li>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.)</li>
-
     </ul></li> <!-- New features -->
 
     <li><b>Improvements to the EFI drivers:</b>
 
     <ul>
 
-    <li>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
+    <li>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.</li>
 
index 341045d0e34da4c22c9fffa6625c41024a9e97a7..399352ccac7143f3c0ea1e8d06f64ecbc4a50e9f 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 3/14/2012; last Web page update:
-12/6/2012, referencing rEFInd 0.5.0</p>
+12/16/2012, referencing rEFInd 0.6.0</p>
 
 
 <p>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!</p>
index 7df71aa740371174225f44d436decf246a3f4ce5..3e96e6200f17f2dc39d13621a841d31f140fcfd9 100644 (file)
@@ -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 (file)
index 0000000..32ac2ed
Binary files /dev/null and b/icons/transparent.icns differ
index 7e2fef4a89c16e96462651e467a8cc152a605e13..e28fb41289c220d5d8c09d61e372024d3c15ffbe 100755 (executable)
@@ -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
 #
 #
 # 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 (file)
index 0000000..5376570
--- /dev/null
@@ -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 (file)
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 (file)
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 (file)
index 0000000..614f6d2
--- /dev/null
@@ -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-----
index 89ddb740cdfda2d18c412428b17df98d9047f9b8..e993ee188c3f959cae0018393e46bf4dd3ad8d96 100644 (file)
@@ -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__ */
 
index 8c7f1e1a5825a902890c6ff71fe181109d0aa62a..400a65c5f41f9702b2f6178f2e6a27c3f7538a35 100644 (file)
@@ -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,
index b3327042c013ff8e25f7cc52a36e865d676ca52e..e4f585afae7ad23c30166b906b39e70244ad398b 100644 (file)
  * (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 <efiUgaDraw.h>
@@ -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);
     }
 }
 
index d84eeb7de3ca3c7e13816af6e458512acc104e26..93551b2b082558d615166eb3b392cfa2a83d2e50 100644 (file)
@@ -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;
 
index e55521b2d195ba7f49bc8b39b3c709a75e3d568e..78f24e31af2d9306d9b4ab6e487c38f87b14cd7f 100755 (executable)
--- 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"
 # 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 (executable)
index 0000000..c12ee8a
--- /dev/null
@@ -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
index 42c73fce309ee5b97a7670dfcc016d8bd7083c2e..7d77fdef8ea25bc09884ca6f359c01d2f085cfa9 100644 (file)
@@ -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
index e2750858308fc75d6cd2391d3d39c138ab316e88..b1e09294ca558a9e78d5c3043da362d67ce1704b 100644 (file)
@@ -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);
index 5e5b042d9d9bd774e8fb8cd6bf2bc159ec003ceb..bc211a98ac74605803cf9de9ce07135457e9dd82 100644 (file)
@@ -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);
index c993b446c3ce3929edf6f0269813daef7e0edf57..511dcace4ee70fc645781c8f953e9e3652b9fe36 100644 (file)
  */
 /*
  * 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_
 #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;
index 77e6842404b4cfe7a7ffb56f4c74d3e9bb1d39d2..958bb525712565ecb778d99379a76f09411f41f0 100644 (file)
@@ -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)
index 1e74ac94dbd9347b7bb30f3e36c79bdad9c2b26b..4e936a8323d2fe69db2efdfeb99cb76963cfd11f 100644 (file)
  */
 /*
  * 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
index 3ff6255f51bb2c61a9fdf489f7fa3e5935ef6651..22693f1732118e2968cbeb1418248e0d647c6d40 100644 (file)
 
 #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"
 // 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;
 
index a6e72ad95d95887dc95d374f00562931e6cdea3d..7de9d8bc3b9d462a0d590984cd00bc9ef7a61287 100644 (file)
  */
 /*
  * 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)
index 4fbfb220b22f2a17f3a6ea580153017471e60b73..d9545d52e99bb9e09540d47f9645ff3585f5b400 100644 (file)
@@ -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);
index cd5c6983b0c0de23c502bf293b6a89f91ce153bb..32711d60e43df1ef466db8d4e01e0f13770f5a3a 100644 (file)
  * (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;
index b89fe8fd608ab20653bc90a8a153bb87befa5b4f..b03f6e17d4922555aeacfff73dc78bfe88ddaf6b 100644 (file)
@@ -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