0.8.7 (?/??/2015):
------------------
+- Added identification of XFS as filesystem type in volume descriptions.
+
+- More fixes to filesystem type detection code. Previous version sometimes
+ identified FAT or NTFS (or anything with a boot loader) as a whole-disk
+ device rather than the correct filesystem type.
+
+- Added protections to the code to reduce the risk of crashes that might
+ occur when dereferencing NULL pointers in various situations.
+
+- I'm deprecating the use of filesystem numbers (as in "fs0:") because
+ they're unreliable -- filesystem numbers can change between boots and
+ might not be the same as those used in an EFI shell or other program.
+ Sooner or later I'll remove code supporting this feature. In the
+ meantime, if it doesn't work for you, please switch to using filesystem
+ labels, partition labels, or partition GUIDs.
+
- Added detection of FreeBSD's BIOS-mode GPT boot loader. Previously,
rEFInd could detect FreeBSD's BIOS-mode MBR boot loader, which gave
- FreeBSD an appropriate icon on Macs; but the GPT boot loader code is
- different, so some recent FreeBSD installations showed up with generic
- grey diamond icons. This change creates FreeBSD icons instead.
+ FreeBSD an appropriate icon on Macs; but the BIOS-mode GPT boot loader
+ code is different, so some recent FreeBSD installations showed up with
+ generic grey diamond icons. This change creates FreeBSD icons instead.
- Added "Secure Boot [active|inactive]" notice to "about" menu for x86
(32-bit) systems, since there are now a few 32-bit UEFI systems that
<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. You may precede a directory path with a volume name and colon, as in <tt>somevol:/extra/path</tt>, to restrict the extra scan to a single volume. A volume number, preceded by <tt>fs</tt>, can be used for volumes that lack names, as in <tt>fs1:/extra/path</tt>. If you don't specify a volume name or number, this option is 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. To add to, rather than replace, the default value, specify <tt>+</tt> as the first item in the list, as in <tt>also_scan_dirs +,loaders</tt>.</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. You may precede a directory path with a volume name and colon, as in <tt>somevol:/extra/path</tt>, to restrict the extra scan to a single volume. A volume number, preceded by <tt>fs</tt>, can be used for volumes that lack names, as in <tt>fs1:/extra/path</tt>. (<i>This usage is deprecated.</i>) If you don't specify a volume name or number, this option is 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. To add to, rather than replace, the default value, specify <tt>+</tt> as the first item in the list, as in <tt>also_scan_dirs +,loaders</tt>.</td>
</tr>
<tr>
<td><tt>dont_scan_volumes</tt> or <tt>don't_scan_volumes</tt></td>
<tr>
<td><tt>dont_scan_dirs</tt> or <tt>don't_scan_dirs</tt></td>
<td>directory path(s)</td>
- <td>Adds the specified directory or directories to a directory "blacklist"—these directories are <i>not</i> scanned for boot loaders. You may optionally precede a directory path with a volume name and a colon to limit the blacklist to that volume; otherwise all volumes are affected. For instance, <tt>EFI/BOOT</tt> prevents scanning the <tt>EFI/BOOT</tt> directory on <i>all</i> volumes, whereas <tt>ESP:EFI/BOOT</tt> blocks scans of <tt>EFI/BOOT</tt> on the volume called <tt>ESP</tt> but not on other volumes. You can use a filesystem number, as in <tt>fs0</tt>, in place of a volume name. This token may be useful to keep duplicate boot loaders out of the menu; or to keep drivers or utilities out of the boot menu, if you've stored them in a subdirectory of <tt>EFI</tt>. This option takes precedence over <tt>also_scan_dirs</tt>; if a directory appears in both lists, it will <i>not</i> be scanned. To add directories to the default list rather than replace the list, specify <tt>+</tt> as the first option, as in <tt>dont_scan_dirs + EFI/dontscan</tt>. The default for this token is <tt>EFI/tools, EFI/tools/memtest86, EFI/tools/memtest, EFI/memtest86, EFI/memtest, com.apple.recovery.boot</tt>.</td>
+ <td>Adds the specified directory or directories to a directory "blacklist"—these directories are <i>not</i> scanned for boot loaders. You may optionally precede a directory path with a volume name and a colon to limit the blacklist to that volume; otherwise all volumes are affected. For instance, <tt>EFI/BOOT</tt> prevents scanning the <tt>EFI/BOOT</tt> directory on <i>all</i> volumes, whereas <tt>ESP:EFI/BOOT</tt> blocks scans of <tt>EFI/BOOT</tt> on the volume called <tt>ESP</tt> but not on other volumes. You can use a filesystem number, as in <tt>fs0</tt>, in place of a volume name. (<i>The use of filesystem numbers is deprecated.</i>) This token may be useful to keep duplicate boot loaders out of the menu; or to keep drivers or utilities out of the boot menu, if you've stored them in a subdirectory of <tt>EFI</tt>. This option takes precedence over <tt>also_scan_dirs</tt>; if a directory appears in both lists, it will <i>not</i> be scanned. To add directories to the default list rather than replace the list, specify <tt>+</tt> as the first option, as in <tt>dont_scan_dirs + EFI/dontscan</tt>. The default for this token is <tt>EFI/tools, EFI/tools/memtest86, EFI/tools/memtest, EFI/memtest86, EFI/memtest, com.apple.recovery.boot</tt>.</td>
</tr>
<tr>
<td><tt>dont_scan_files</tt> or <tt>don't_scan_files</tt></td>
EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
EFI_GUID gEfiComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
-extern EFI_GUID gEfiDiskIoProtocolGuid = EFI_DISK_IO_PROTOCOL_GUID;
-extern EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+EFI_GUID gEfiDiskIoProtocolGuid = EFI_DISK_IO_PROTOCOL_GUID;
+EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
EFI_GUID gEfiFileInfoGuid = EFI_FILE_INFO_ID;
EFI_GUID gEfiFileSystemInfoGuid = EFI_FILE_SYSTEM_INFO_ID;
EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid = EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID;
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
- * Modifications copyright (c) 2012-2014 Roderick W. Smith
+ * Modifications copyright (c) 2012-2015 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
// Basic file operations
//
-EFI_STATUS egLoadFile(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileDataLength)
+EFI_STATUS egLoadFile(IN EFI_FILE *BaseDir, IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileDataLength)
{
EFI_STATUS Status;
EFI_FILE_HANDLE FileHandle;
UINTN BufferSize;
UINT8 *Buffer;
+ if ((BaseDir == NULL) || (FileName == NULL))
+ return EFI_NOT_FOUND;
+
Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR(Status)) {
return Status;
}
} /* VOID egComposeImage() */
-// EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN UINTN Width, IN UINTN Height, IN EG_PIXEL *Color)
-// {
-// EG_IMAGE *NewImage;
-//
-// if (Image == NULL)
-// return NULL;
-// if (Image->Width == Width && Image->Height == Height)
-// return Image;
-//
-// NewImage = egCreateFilledImage(Width, Height, Image->HasAlpha, Color);
-// if (NewImage == NULL) {
-// egFreeImage(Image);
-// return NULL;
-// }
-// Image->HasAlpha = FALSE;
-// egComposeImage(NewImage, Image, 0, 0);
-// egFreeImage(Image);
-//
-// return NewImage;
-// }
-
//
// misc internal functions
//
static VOID SetDefaultByTime(IN CHAR16 **TokenList, OUT CHAR16 **Default) {
EFI_STATUS Status;
EFI_TIME CurrentTime;
- UINTN StartTime = LAST_MINUTE + 1, EndTime = LAST_MINUTE + 1, Now;
+ UINTN StartTime, EndTime, Now;
BOOLEAN SetIt = FALSE;
StartTime = HandleTime(TokenList[2]);
} else if ((StriCmp(TokenList[0], L"volume") == 0) && (TokenCount > 1)) {
if (FindVolume(&Volume, TokenList[1])) {
- MyFreePool(SubEntry->me.Title);
- SubEntry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
- SPrint(SubEntry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", Volume->VolName);
- SubEntry->me.BadgeImage = Volume->VolBadgeImage;
- SubEntry->VolName = Volume->VolName;
+ if ((Volume != NULL) && (Volume->IsReadable) && (Volume->RootDir)) {
+ MyFreePool(SubEntry->me.Title);
+ SubEntry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
+ SPrint(SubEntry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", Volume->VolName);
+ SubEntry->me.BadgeImage = Volume->VolBadgeImage;
+ SubEntry->VolName = Volume->VolName;
+ } // if volume is readable
} // if match found
} else if (StriCmp(TokenList[0], L"initrd") == 0) {
} else if ((StriCmp(TokenList[0], L"volume") == 0) && (TokenCount > 1)) {
if (FindVolume(&CurrentVolume, TokenList[1])) {
- MyFreePool(Entry->me.Title);
- Entry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
- SPrint(Entry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", CurrentVolume->VolName);
- Entry->me.BadgeImage = CurrentVolume->VolBadgeImage;
- Entry->VolName = CurrentVolume->VolName;
+ if ((CurrentVolume != NULL) && (CurrentVolume->IsReadable) && (CurrentVolume->RootDir)) {
+ MyFreePool(Entry->me.Title);
+ Entry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
+ SPrint(Entry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", CurrentVolume->VolName);
+ Entry->me.BadgeImage = CurrentVolume->VolBadgeImage;
+ Entry->VolName = CurrentVolume->VolName;
+ } // if volume is readable
} // if match found
} else if ((StriCmp(TokenList[0], L"icon") == 0) && (TokenCount > 1)) {
#define FS_TYPE_HFSPLUS 8
#define FS_TYPE_REISERFS 9
#define FS_TYPE_BTRFS 10
-#define FS_TYPE_ISO9660 11
+#define FS_TYPE_XFS 11
+#define FS_TYPE_ISO9660 12
// How to scale banner images
#define BANNER_NOSCALE 0
#include "../include/RemovableMedia.h"
#include "gpt.h"
#include "config.h"
+#include "../EfiLib/LegacyBios.h"
#ifdef __MAKEWITH_GNUEFI
#define EfiReallocatePool ReallocatePool
#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
#define BTRFS_SIGNATURE "_BHRfS_M"
+#define XFS_SIGNATURE "XFSB"
#define NTFS_SIGNATURE "NTFS "
// variables
case FS_TYPE_BTRFS:
retval = L" Btrfs";
break;
+ case FS_TYPE_XFS:
+ retval = L" XFS";
+ break;
case FS_TYPE_ISO9660:
retval = L" ISO-9660";
break;
SetMem(&(Volume->VolUuid), sizeof(EFI_GUID), 0);
Volume->FSType = FS_TYPE_UNKNOWN;
- if (BufferSize >= 512) {
-
- // Search for NTFS, FAT, and MBR/EBR.
- // These all have 0xAA55 at the end of the first sector, but FAT and
- // MBR/EBR are not easily distinguished. Thus, we first check to see
- // if the "volume" is in fact a disk device; then look for NTFS
- // "magic"; and then check to see if the volume can be mounted, thus
- // relying on the EFI's built-in FAT driver to identify FAT.
- Magic16 = (UINT16*) (Buffer + 510);
- if (*Magic16 == FAT_MAGIC) {
- MagicString = (char*) (Buffer + 3);
- // Confusingly, "LogicalPartition" refers to the presence of a
- // partition table, not an MBR logical partition.
- if (Volume->BlockIO->Media->LogicalPartition) {
- Volume->FSType = FS_TYPE_WHOLEDISK;
- } else if (CompareMem(MagicString, NTFS_SIGNATURE, 8) == 0) {
- Volume->FSType = FS_TYPE_NTFS;
- CopyMem(&(Volume->VolUuid), Buffer + 0x48, sizeof(UINT64));
- } else {
- RootDir = LibOpenRoot(Volume->DeviceHandle);
- if (RootDir != NULL)
- Volume->FSType = FS_TYPE_FAT;
- } // if/elseif/else
- return;
- } // if
- } // search for FAT and NTFS magic
-
if (BufferSize >= (1024 + 100)) {
Magic16 = (UINT16*) (Buffer + 1024 + 56);
if (*Magic16 == EXT2_SUPER_MAGIC) { // ext2/3/4
} // if
} // search for Btrfs magic
+ if (BufferSize >= 512) {
+ MagicString = (char*) Buffer;
+ if (CompareMem(MagicString, XFS_SIGNATURE, 4) == 0) {
+ Volume->FSType = FS_TYPE_XFS;
+ return;
+ }
+ } // search for XFS magic
+
if (BufferSize >= (1024 + 2)) {
Magic16 = (UINT16*) (Buffer + 1024);
if ((*Magic16 == HFSPLUS_MAGIC1) || (*Magic16 == HFSPLUS_MAGIC2)) {
}
} // search for HFS+ magic
- } // if (Buffer != NULL)
+ if (BufferSize >= 512) {
+ // Search for NTFS, FAT, and MBR/EBR.
+ // These all have 0xAA55 at the end of the first sector, but FAT and
+ // MBR/EBR are not easily distinguished. Thus, we first look for NTFS
+ // "magic"; then check to see if the volume can be mounted, thus
+ // relying on the EFI's built-in FAT driver to identify FAT; and then
+ // check to see if the "volume" is in fact a whole-disk device.
+ Magic16 = (UINT16*) (Buffer + 510);
+ if (*Magic16 == FAT_MAGIC) {
+ MagicString = (char*) (Buffer + 3);
+ if (CompareMem(MagicString, NTFS_SIGNATURE, 8) == 0) {
+ Volume->FSType = FS_TYPE_NTFS;
+ CopyMem(&(Volume->VolUuid), Buffer + 0x48, sizeof(UINT64));
+ } else {
+ RootDir = LibOpenRoot(Volume->DeviceHandle);
+ if (RootDir != NULL) {
+ Volume->FSType = FS_TYPE_FAT;
+ } else if (!Volume->BlockIO->Media->LogicalPartition) {
+ Volume->FSType = FS_TYPE_WHOLEDISK;
+ } // if/elseif/else
+ } // if/else
+ return;
+ } // if
+ } // search for FAT and NTFS magic
+
+ } // if ((Buffer != NULL) && (Volume != NULL))
} // UINT32 SetFilesystemData()
Volume->BlockIOOffset, SAMPLE_SIZE, Buffer);
if (!EFI_ERROR(Status)) {
-// if (Volume->BlockIO->Media->LogicalPartition)
-// Print(L"Skipping; whole disk!\n");
-// else
- SetFilesystemData(Buffer, SAMPLE_SIZE, Volume);
-// PauseForKey();
+ SetFilesystemData(Buffer, SAMPLE_SIZE, Volume);
if ((*((UINT16 *)(Buffer + 510)) == 0xaa55 && Buffer[0] != 0) && (FindMem(Buffer, 512, "EXFAT", 5) == -1)) {
*Bootable = TRUE;
Volume->HasBootCode = TRUE;
BOOLEAN FileExists(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath)
{
- EFI_STATUS Status;
- EFI_FILE_HANDLE TestFile;
-
- Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &TestFile, RelativePath, EFI_FILE_MODE_READ, 0);
- if (Status == EFI_SUCCESS) {
- refit_call1_wrapper(TestFile->Close, TestFile);
- return TRUE;
- }
- return FALSE;
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE TestFile;
+
+ if (BaseDir != NULL) {
+ Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &TestFile, RelativePath, EFI_FILE_MODE_READ, 0);
+ if (Status == EFI_SUCCESS) {
+ refit_call1_wrapper(TestFile->Close, TestFile);
+ return TRUE;
+ }
+ }
+ return FALSE;
}
EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, IN UINTN FilterMode)
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.6.4");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.6.6");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2015 Roderick W. Smith");
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Boot Linux for a 17\" iMac or a 15\" MacBook Pro (*)";
- SubEntry->UseGraphicsMode = TRUE;
SubEntry->LoadOptions = L"-d 0 i17";
SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO;
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Boot Linux for a 20\" iMac (*)";
- SubEntry->UseGraphicsMode = TRUE;
SubEntry->LoadOptions = L"-d 0 i20";
SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO;
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Boot Linux for a Mac Mini (*)";
- SubEntry->UseGraphicsMode = TRUE;
SubEntry->LoadOptions = L"-d 0 mini";
SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO;
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Run XOM in text mode";
- SubEntry->UseGraphicsMode = FALSE;
SubEntry->LoadOptions = L"-v";
SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS;
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS;
} else if (StriCmp(NameClues, L"xom.efi") == 0) {
MergeStrings(&OSIconName, L"xom,win,win8", L',');
- Entry->UseGraphicsMode = TRUE;
Entry->OSType = 'X';
ShortcutLetter = 'W';
Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS;
UINTN i;
UINTN Sum = 0;
- if (Image != NULL) {
+ if ((Image != NULL) && ((Image->Width * Image->Height) != 0)) {
for (i = 0; i < (Image->Width * Image->Height); i++) {
Sum += (Image->PixelData[i].r + Image->PixelData[i].g + Image->PixelData[i].b);
}
+ Sum /= (Image->Width * Image->Height * 3);
} // if
- return (UINT8) (Sum / (Image->Width * Image->Height * 3));
+ return (UINT8) Sum;
} // UINT8 AverageBrightness()
// Display text against the screen's background image. Special case: If Text is NULL
}
// blit to screen and clean up
- if (CompImage->HasAlpha)
- egDrawImageWithTransparency(CompImage, NULL, XPos, YPos, CompImage->Width, CompImage->Height);
- else
- egDrawImage(CompImage, XPos, YPos);
- egFreeImage(CompImage);
- GraphicsScreenDirty = TRUE;
+ if (CompImage != NULL) {
+ if (CompImage->HasAlpha)
+ egDrawImageWithTransparency(CompImage, NULL, XPos, YPos, CompImage->Width, CompImage->Height);
+ else
+ egDrawImage(CompImage, XPos, YPos);
+ egFreeImage(CompImage);
+ GraphicsScreenDirty = TRUE;
+ }
}
// Line-editing functions borrowed from gummiboot (cursor_left(), cursor_right(), & line_edit()).