From 1f5e6865fb9bf8ebb78b4818a6d54440c7c4004a Mon Sep 17 00:00:00 2001 From: srs5694 Date: Mon, 9 Apr 2012 17:55:56 -0400 Subject: [PATCH] Version 0.2.5 release. Additional icon-management changes. --- Makefile | 4 +- NEWS.txt | 17 +++++- docs/refind/bootmode.html | 2 +- docs/refind/configfile.html | 10 +++- docs/refind/features.html | 7 +-- docs/refind/getting.html | 12 ++-- docs/refind/index.html | 2 +- docs/refind/installing.html | 10 +--- docs/refind/linux.html | 24 ++++++-- docs/refind/revisions.html | 8 ++- docs/refind/todo.html | 6 +- docs/refind/using.html | 2 +- libeg/image.c | 22 +++---- libeg/load_icns.c | 38 ++++++------ mkcdimage | 8 ++- refind/config.c | 10 ++-- refind/global.h | 1 + refind/lib.c | 113 +++++++++++++++++++----------------- refind/main.c | 21 +++++-- 19 files changed, 184 insertions(+), 133 deletions(-) diff --git a/Makefile b/Makefile index f596309..2b7a549 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,8 @@ LIB_DIR=libeg # Build the Symbiote library itself. all: - make -C $(LIB_DIR) -j 6 - make -C $(LOADER_DIR) -j 6 + make -C $(LIB_DIR) + make -C $(LOADER_DIR) clean: make -C $(LIB_DIR) clean diff --git a/NEWS.txt b/NEWS.txt index e0a3e84..9b1307e 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,5 +1,18 @@ -0.2.5 (?/??/2012): ------------------- +0.2.5 (4/9/2012): +----------------- + +- Fixed bug that caused an inability to associate initial RAM disks with + Linux kernels stored in a volume's root directory. + +- Volume badges (that override default badges) are now stored in + .VolumeBadge.icns. Although undocumented, rEFInd formerly loaded custom + volume badges from .VolumeIcon.icns. This carryover from rEFIt was a + confusing name, given the next (new) feature, so I've changed and + documented the name.... + +- Added ability to set a default icon for a loader stored in the root + directory of a volume: The icon is stored in .VolumeIcon.icns. This icon + is also used for Mac OS X volumes booted from the standard location. - Fixed bug that caused icons to drop back to generic icons when rEFInd was launched in certain ways (such as from an EFI shell in rEFInd's diff --git a/docs/refind/bootmode.html b/docs/refind/bootmode.html index c1fa857..d4f48d9 100644 --- a/docs/refind/bootmode.html +++ b/docs/refind/bootmode.html @@ -14,7 +14,7 @@

by Roderick W. Smith, rodsmith@rodsbooks.com

-

Originally written: 3/14/2012; last Web page update: 4/5/2012, referencing rEFInd 0.2.4

+

Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!

diff --git a/docs/refind/configfile.html b/docs/refind/configfile.html index 9931f92..95720e5 100644 --- a/docs/refind/configfile.html +++ b/docs/refind/configfile.html @@ -14,7 +14,7 @@

by Roderick W. Smith, rodsmith@rodsbooks.com

-

Originally written: 3/14/2012; last Web page update: 4/5/2012, referencing rEFInd 0.2.4

+

Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

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!

@@ -103,7 +103,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

Another way to hide a boot loader is to move it into rEFInd's own directory. In order to keep rEFInd from showing up in its own menu, it ignores boot loaders in its own directory. This obviously includes the rEFInd binary file itself, but also anything else you might store there.

-

In addition to hiding boot loaders, you can adjust their icons. You can do this in either of two ways:

+

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:

-

rEFInd assigns icons to the Windows and OS X boot loaders based on their conventional locations, so they get suitable icons even though they don't follow these rules.

+

As a special case, rEFInd assigns icons to the Windows and OS X boot loaders based on their conventional locations, so they get suitable icons even though they don't follow these rules.

+ +

In addition to the main OS tag icon, you can set the badge icon for a volume by creating a file called .VolumeBadge.icns in the root directory of a partition. This icon file must include a 32x32 bitmap. If present, it replaces the disk-type icons that are overlaid on the main OS icon. If you use this feature, the badge is applied to all the boot loaders read from the disk, not just those stored in the root directory or the Apple boot loader location. You could use this feature to set a custom badge for different specific disks or to help differentiate multiple OS X installations on one computer.

Adjusting the Global Configuration

diff --git a/docs/refind/features.html b/docs/refind/features.html index b81b2e7..13508ae 100644 --- a/docs/refind/features.html +++ b/docs/refind/features.html @@ -11,11 +11,10 @@

The rEFInd Boot Manager:
rEFInd Features

-

by Roderick W. Smith, by Roderick W. Smith, rodsmith@rodsbooks.com

-

Originally written: 3/14/2012; last Web page update: 4/5/2012, referencing rEFInd 0.2.4

- +

Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

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!

@@ -101,7 +100,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

  • Launch EFI boot loaders or, on Macs, launch BIOS-based boot loaders. (I have yet to get the BIOS-launching feature to work on a UEFI-based PC, but it might work on a model I don't own.)
  • -
  • Launch options for an EFI shell, disk partitioner, and other optional external components. (See the Installing rEFInd section for information on how to obtain and install these components.)
  • +
  • Launch options for an external EFI shell or disk partitioner. (See the Installing rEFInd section for information on how to obtain and install these components.)
  • Set OS-specific boot options, such as to launch Mac OS X with verbose text-mode debug messages.
  • diff --git a/docs/refind/getting.html b/docs/refind/getting.html index a3c44e7..a5e6905 100644 --- a/docs/refind/getting.html +++ b/docs/refind/getting.html @@ -14,7 +14,7 @@

    by Roderick W. Smith, rodsmith@rodsbooks.com

    -

    Originally written: 3/14/2012; last Web page update: 4/5/2012, referencing rEFInd 0.2.4

    +

    Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

    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!

    @@ -96,7 +96,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

    I've seen links to other versions of these tools from time to time on the Web, so if you try one of these programs and it crashes or behaves strangely, try performing a Web search; you may turn up something that works better for you than the one to which I've linked.

    diff --git a/docs/refind/linux.html b/docs/refind/linux.html index 3508243..939e798 100644 --- a/docs/refind/linux.html +++ b/docs/refind/linux.html @@ -9,12 +9,12 @@ -

    The rEFInd Boot Manager:
    Methods of Booting Linux

    +

    The rEFInd Boot Manager:
    Methods of Booting Linux

    -

    by Roderick W. Smith, by Roderick W. Smith, rodsmith@rodsbooks.com

    -

    Originally written: 3/19/2012; last Web page update: 4/5/2012, referencing rEFInd 0.2.4

    +

    Originally written: 3/19/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

    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!

    @@ -105,13 +105,25 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

    The Linux EFI stub loader is a way to turn a Linux kernel into an EFI application. In a sense, the kernel becomes its own boot loader. This approach to booting Linux is very elegant in some ways, but as described on the page to which I just linked, it has its disadvantages, too. One challenge to booting in this way is that modern Linux installations typically require that the kernel be passed a number of options at boot time. These tell the kernel where the Linux root (/) filesystem is, where the initial RAM disk is, and so on. Without these options, Linux won't boot. These options are impossible for a generic boot loader to guess without a little help. It's possible to build a kernel with a default set of options, but this is rather limiting. Thus, rEFInd provides configuration options to help.

    -

    With all versions of rEFInd, you can create manual boot loader stanzas in the refind.conf file to identify a Linux kernel and to pass it all the options it needs. This approach is effective and flexible, but it requires editing a single configuration file. If a computer boots two different Linux distributions, and if both were to support rEFInd, problems might arise as each one tries 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.

    +

    With all versions of rEFInd, you can create manual boot loader stanzas +in the refind.conf file to identify a Linux kernel and to pass it +all the options it needs. This approach is effective and flexible, but it +requires editing a single configuration file for all the OSes you want to +define in this way. If a computer boots two different Linux distributions, +and if both were to support rEFInd, problems might arise as each one tries +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.

    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:

      -
    1. rEFInd looks for boot loaders whose names include the strings bzImage or vmlinuz and that end in .efi. For instance, bzImage-3.3.0.efi or vmlinuz-3.3.0-fc17.efi would match, and trigger subsequent steps in this procedure. Note that to use this system, you must give your kernel file a .efi extension, at least on the ESP (or other boot loader partition, for Macs)!
    2. +
    3. rEFInd looks for boot loaders whose names include the strings bzImage or vmlinuz and that end in .efi. For instance, bzImage-3.3.0.efi or vmlinuz-3.3.0-fc17.efi would match, and trigger subsequent steps in this procedure. Note that to use this system, you must give your kernel file a .efi extension, at least on the ESP (or other boot loader partition)!
    4. @@ -172,6 +184,8 @@ total 17943 + +

      On the whole, this method of configuration has a lot going for it. For distribution maintainers, if you place your Linux kernel files (with EFI stub support) on the ESP, with suitable filenames, matching initial RAM disk files, and a refind_linux.conf file, then any rEFInd 0.2.3 or later installation should detect your files, even if the user installs another distribution with another rEFInd that takes over from yours. (If the user, or this other rEFInd installation, disables auto-detection, this won't work.)

      For end users, this method is simpler than maintaining manual configurations in refind.conf (or equivalents for ELILO or GRUB). To install a new kernel, you need only copy it and its initial RAM disk, under suitable names, to a scanned directory on the ESP. There's no need to touch any configuration file, provided you've already set up refind_linux.conf in your kernel's directory. You will, however, have to adjust refind_linux.conf if you make certain changes, such as if your root directory identifier changes.

      diff --git a/docs/refind/revisions.html b/docs/refind/revisions.html index 2cb3326..bb06648 100644 --- a/docs/refind/revisions.html +++ b/docs/refind/revisions.html @@ -9,12 +9,12 @@ -

      The rEFInd Boot Manager:
      Revisions

      +

      The rEFInd Boot Manager:
      Revisions

      -

      by Roderick W. Smith, by Roderick W. Smith, rodsmith@rodsbooks.com

      -

      Last Web page update: 4/5/2012

      +

      Last Web page update: 4/9/2012

      I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!

      @@ -93,6 +93,8 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

        +
      • 0.2.5 (4/9/2012)—Icon-handling improvements are key in this version. I've fixed a bug that caused icons to be replaced with ugly "not-found" default icons when rEFInd was launched in certain ways. I've also added support for .VolumeIcon.icns and .VolumeBadge.icns files to set loader tags and disk-type badges, respectively. (See the configuration page for details.) I've also fixed a bug that prevented rEFInd from finding the correct initial RAM disk for Linux kernels stored in the root directory of a partition.
      • +
      • 0.2.4 (4/5/2012)—This version adds support for a new location for EFI shells (shellarch.efi in the ESP's root directory. It also adds two new refind.conf options: showtools and max_tags, and removes another one (disable). The options available in hideui are now essentially a combination of what disable and hideui did, minus functionality now present in showtools. I made these changes to reduce redundancy and to increase flexibility. See the Configuring the Boot Manager page for details.
      • 0.2.3 (3/26/2012)—I've changed the Linux kernel configuration filename from linux.conf to refind_linux.conf with this version, to avoid a name collision with a planned future Linux kernel ability to read its options from a file called linux.conf. This version also includes a tentative bug fix for a problem that caused rEFInd to hang upon launching the second program (say, a boot loader after using a shell) on some systems; but on some computers, this fix causes an (apparently harmless) error message about "(re)opening our installation volume" upon returning from the first program. I've also added a logo for Arch Linux.
      • diff --git a/docs/refind/todo.html b/docs/refind/todo.html index efc4481..a867890 100644 --- a/docs/refind/todo.html +++ b/docs/refind/todo.html @@ -14,7 +14,7 @@

        by Roderick W. Smith, rodsmith@rodsbooks.com

        -

        Originally written: 3/14/2012; last Web page update: 4/5/2012, referencing rEFInd 0.2.4

        +

        Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

        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!

        @@ -89,7 +89,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com


        -

        rEFInd is far from perfect. It's based on rEFIt, which has an list of active bugs on its project page on Sourceforge. I have not studied this bug list in detail for rEFInd's first release, although I've probably fixed a few of those bugs because I encountered them myself. Other bugs I may never fix because I lack the necessary hardware for testing.

        +

        rEFInd is far from perfect. It's based on rEFIt, which has a list of active bugs on its project page on Sourceforge. I have not studied this bug list in detail for rEFInd's first release, although I've probably fixed a few of those bugs because I encountered them myself. Other bugs I may never fix because I lack the necessary hardware for testing.

        This page exists to document some of rEFInd's known bugs and limitations, as well as features I hope to add in the future. Some of the items on this list are things that you may be able to help with, so if you'd like to contribute, feel free to drop me a line!

        @@ -117,6 +117,8 @@ program. I'm not sure what you'd use in Windows to create ICNS files.
      • The code could be more flexible in its handling of the sizes of various graphical elements, and particularly drawn text. Prior to version 0.2.2, submenu text was invisible on UEFI-based PCs with 800x600 and smaller displays because of an inability to properly crop the graphics fields that hold the text. With version 0.2.2, I've put a band-aid on this problem by reducing the field size so that it now works on 800x600 displays, but smaller displays still suffer from this problem. This is just an example of the inflexibility of certain layout issues within rEFInd.
      • +
      • Although the ICNS file format used by rEFInd supports multiple image sizes, if a size that rEFInd needs isn't present in the file, rEFInd can't use the icon. The ability to scale images to the desired size would be useful.
      • +
      • I want to be able to specify the volume on which a boot loader resides in refind.conf. (As it is, manually-defined options can only launch boot loader files on the same volume as rEFInd.)
      • It would be useful to be able to specify paths to boot loaders and/or initial RAM disks relative to the rEFInd directory (or the boot loader's directory, in the case of initrds).
      • diff --git a/docs/refind/using.html b/docs/refind/using.html index e41df8d..2c93755 100644 --- a/docs/refind/using.html +++ b/docs/refind/using.html @@ -14,7 +14,7 @@

        by Roderick W. Smith, rodsmith@rodsbooks.com

        -

        Originally written: 3/14/2012; last Web page update: 4/5/2012, referencing rEFInd 0.2.4

        +

        Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

        I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!

        diff --git a/libeg/image.c b/libeg/image.c index 5907c09..13bb758 100644 --- a/libeg/image.c +++ b/libeg/image.c @@ -77,11 +77,11 @@ EG_IMAGE * egCreateFilledImage(IN UINTN Width, IN UINTN Height, IN BOOLEAN HasAl EG_IMAGE * egCopyImage(IN EG_IMAGE *Image) { EG_IMAGE *NewImage; - + NewImage = egCreateImage(Image->Width, Image->Height, Image->HasAlpha); if (NewImage == NULL) return NULL; - + CopyMem(NewImage->PixelData, Image->PixelData, Image->Width * Image->Height * sizeof(EG_PIXEL)); return NewImage; } @@ -221,7 +221,7 @@ static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength, } else if ((StriCmp(Format, L"ICNS") == 0) || (StriCmp(Format, L"icns") == 0)) { NewImage = egDecodeICNS(FileData, FileDataLength, IconSize, WantAlpha); } // if/else - + return NewImage; } @@ -231,19 +231,19 @@ EG_IMAGE * egLoadImage(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, IN BOOLEAN Wan UINT8 *FileData; UINTN FileDataLength; EG_IMAGE *NewImage; - + if (BaseDir == NULL || FileName == NULL) return NULL; - + // load file Status = egLoadFile(BaseDir, FileName, &FileData, &FileDataLength); if (EFI_ERROR(Status)) return NULL; - + // decode it NewImage = egDecodeAny(FileData, FileDataLength, egFindExtension(FileName), 128, WantAlpha); FreePool(FileData); - + return NewImage; } @@ -253,24 +253,24 @@ EG_IMAGE * egLoadIcon(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, IN UINTN IconSi UINT8 *FileData; UINTN FileDataLength; EG_IMAGE *NewImage; - + if (BaseDir == NULL || FileName == NULL) return NULL; - + // load file Status = egLoadFile(BaseDir, FileName, &FileData, &FileDataLength); if (EFI_ERROR(Status)) { // Print(L"In egLoadIcon(), Status = %d after egLoadFile(); aborting load!\n", Status); return NULL; } - + // decode it NewImage = egDecodeAny(FileData, FileDataLength, egFindExtension(FileName), IconSize, TRUE); // Print(L"Done with egDecodeAny(), used extension '%s'\n", egFindExtension(FileName)); // if (NewImage == NULL) // Print(L"Returning NULL from egLoadIcon()\n"); FreePool(FileData); - + return NewImage; } diff --git a/libeg/load_icns.c b/libeg/load_icns.c index 6af234d..5477f46 100644 --- a/libeg/load_icns.c +++ b/libeg/load_icns.c @@ -108,14 +108,14 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic // not an icns file... return NULL; } - + FetchPixelSize = IconSize; for (;;) { DataPtr = NULL; DataLen = 0; MaskPtr = NULL; MaskLen = 0; - + Ptr = FileData + 8; BufferEnd = FileData + FileDataLength; // iterate over tagged blocks in the file @@ -123,7 +123,7 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic BlockLen = ((UINT32)Ptr[4] << 24) + ((UINT32)Ptr[5] << 16) + ((UINT32)Ptr[6] << 8) + (UINT32)Ptr[7]; if (Ptr + BlockLen > BufferEnd) // block continues beyond end of file break; - + // extract the appropriate blocks for each pixel size if (FetchPixelSize == 128) { if (Ptr[0] == 'i' && Ptr[1] == 't' && Ptr[2] == '3' && Ptr[3] == '2') { @@ -135,7 +135,7 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic MaskPtr = Ptr + 8; MaskLen = BlockLen - 8; } - + } else if (FetchPixelSize == 48) { if (Ptr[0] == 'i' && Ptr[1] == 'h' && Ptr[2] == '3' && Ptr[3] == '2') { DataPtr = Ptr + 8; @@ -144,7 +144,7 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic MaskPtr = Ptr + 8; MaskLen = BlockLen - 8; } - + } else if (FetchPixelSize == 32) { if (Ptr[0] == 'i' && Ptr[1] == 'l' && Ptr[2] == '3' && Ptr[3] == '2') { DataPtr = Ptr + 8; @@ -153,7 +153,7 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic MaskPtr = Ptr + 8; MaskLen = BlockLen - 8; } - + } else if (FetchPixelSize == 16) { if (Ptr[0] == 'i' && Ptr[1] == 's' && Ptr[2] == '3' && Ptr[3] == '2') { DataPtr = Ptr + 8; @@ -162,12 +162,12 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic MaskPtr = Ptr + 8; MaskLen = BlockLen - 8; } - + } - + Ptr += BlockLen; } - + /* FUTURE: try to load a different size and scale it later if (DataPtr == NULL && FetchPixelSize == 32) { FetchPixelSize = 128; @@ -176,18 +176,18 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic */ break; } - + if (DataPtr == NULL) return NULL; // no image found - + // allocate image structure and buffer NewImage = egCreateImage(FetchPixelSize, FetchPixelSize, WantAlpha); if (NewImage == NULL) return NULL; PixelCount = FetchPixelSize * FetchPixelSize; - + if (DataLen < PixelCount * 3) { - + // pixel data is compressed, RGB planar CompData = DataPtr; CompLen = DataLen; @@ -198,9 +198,9 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic if (CompLen > 0) { Print(L" egLoadICNSIcon: %d bytes of compressed data left\n", CompLen); } - + } else { - + // pixel data is uncompressed, RGB interleaved SrcPtr = DataPtr; DestPtr = NewImage->PixelData; @@ -209,17 +209,17 @@ EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN Ic DestPtr->g = *SrcPtr++; DestPtr->b = *SrcPtr++; } - + } - + // add/set alpha plane if (MaskPtr != NULL && MaskLen >= PixelCount && WantAlpha) egInsertPlane(MaskPtr, PLPTR(NewImage, a), PixelCount); else egSetPlane(PLPTR(NewImage, a), WantAlpha ? 255 : 0, PixelCount); - + // FUTURE: scale to originally requested size if we had to load another size - + return NewImage; } diff --git a/mkcdimage b/mkcdimage index ff58829..b8824f1 100755 --- a/mkcdimage +++ b/mkcdimage @@ -74,6 +74,10 @@ mkisofs -A "Bootable rEFInd" -V "rEFInd $Version" -volset "rEFInd $Version" \ # Create a bootable USB flash drive image, using the FAT filesystem # created above and a stored partition table image (plus some empty # sectors).... +# +# Note: Seems to work on only a few systems, so I'm not distributing +# the resulting images yet.... +# rm ../../refind-flashdrive-$Version.* cat $StartDir/flashparts.img refind-bin-$Version.img > refind-flashdrive-$Version.img cp $StartDir/README-flashdrive.txt ./ @@ -92,7 +96,7 @@ mv refind-flashdrive-$Version/refind-flashdrive-$Version.img ../ cd ../ # Zip up the optical disc image.... -rm refind-cd-$Version.zip +rm -f refind-cd-$Version.zip zip -9 refind-cd-$Version.zip refind-cd-$Version.iso -#rm -r temp/ +rm -r temp/ diff --git a/refind/config.c b/refind/config.c index 955948b..e7ceb17 100644 --- a/refind/config.c +++ b/refind/config.c @@ -109,7 +109,7 @@ static EFI_STATUS ReadFile(IN EFI_FILE_HANDLE BaseDir, CHAR16 *FileName, REFIT_F File->End8Ptr = File->Current8Ptr + File->BufferSize; File->Current16Ptr = (CHAR16 *)File->Buffer; File->End16Ptr = File->Current16Ptr + (File->BufferSize >> 1); - + // detect encoding File->Encoding = ENCODING_ISO8859_1; // default: 1:1 translation of CHAR8 to CHAR16 if (File->BufferSize >= 4) { @@ -126,7 +126,7 @@ static EFI_STATUS ReadFile(IN EFI_FILE_HANDLE BaseDir, CHAR16 *FileName, REFIT_F } // TODO: detect other encodings as they are implemented } - + return EFI_SUCCESS; } @@ -252,10 +252,10 @@ UINTN ReadTokenLine(IN REFIT_FILE *File, OUT CHAR16 ***TokenList) if (*p == 0 || *p == '#') LineFinished = TRUE; *p++ = 0; - + AddListElement((VOID ***)TokenList, &TokenCount, (VOID *)StrDuplicate(Token)); } - + FreePool(Line); } return (TokenCount); @@ -322,7 +322,7 @@ VOID ReadConfig(VOID) TokenCount = ReadTokenLine(&File, &TokenList); if (TokenCount == 0) break; - + if (StriCmp(TokenList[0], L"timeout") == 0) { HandleInt(TokenList, TokenCount, &(GlobalConfig.Timeout)); diff --git a/refind/global.h b/refind/global.h index 1218c44..63bc008 100644 --- a/refind/global.h +++ b/refind/global.h @@ -91,6 +91,7 @@ typedef struct { EFI_HANDLE DeviceHandle; EFI_FILE *RootDir; CHAR16 *VolName; + EG_IMAGE *VolIconImage; EG_IMAGE *VolBadgeImage; UINTN DiskKind; BOOLEAN IsAppleLegacy; diff --git a/refind/lib.c b/refind/lib.c index f5278ae..3c61782 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -63,6 +63,10 @@ UINTN VolumesCount = 0; // Maximum size for disk sectors #define SECTOR_SIZE 4096 +// 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" + // functions static EFI_STATUS FinishInitRefitLib(VOID); @@ -435,7 +439,7 @@ static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootabl CopyMem(Volume->MbrPartitionTable, MbrTable, 4 * 16); } } - + } else { #if REFIT_DEBUG > 0 CheckError(Status, L"while reading boot sector"); @@ -468,7 +472,7 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume) UINTN PartialLength; EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr; BOOLEAN Bootable; - + // get device path Volume->DevicePath = DuplicateDevicePath(DevicePathFromHandle(Volume->DeviceHandle)); #if REFIT_DEBUG > 0 @@ -479,9 +483,9 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume) #endif } #endif - + Volume->DiskKind = DISK_KIND_INTERNAL; // default - + // get block i/o Status = refit_call3_wrapper(BS->HandleProtocol, Volume->DeviceHandle, &BlockIoProtocol, (VOID **) &(Volume->BlockIO)); if (EFI_ERROR(Status)) { @@ -491,16 +495,16 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume) if (Volume->BlockIO->Media->BlockSize == 2048) Volume->DiskKind = DISK_KIND_OPTICAL; } - + // scan for bootcode and MBR table Bootable = FALSE; ScanVolumeBootcode(Volume, &Bootable); - + // detect device type DevicePath = Volume->DevicePath; while (DevicePath != NULL && !IsDevicePathEndType(DevicePath)) { NextDevicePath = NextDevicePathNode(DevicePath); - + if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH && (DevicePathSubType(DevicePath) == MSG_USB_DP || DevicePathSubType(DevicePath) == MSG_USB_CLASS_DP || @@ -512,44 +516,44 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume) Volume->DiskKind = DISK_KIND_OPTICAL; // El Torito entry -> optical disk Bootable = TRUE; } - + if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH && DevicePathSubType(DevicePath) == MEDIA_VENDOR_DP) { Volume->IsAppleLegacy = TRUE; // legacy BIOS device entry // TODO: also check for Boot Camp GUID Bootable = FALSE; // this handle's BlockIO is just an alias for the whole device } - + if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH) { // make a device path for the whole device PartialLength = (UINT8 *)NextDevicePath - (UINT8 *)(Volume->DevicePath); DiskDevicePath = (EFI_DEVICE_PATH *)AllocatePool(PartialLength + sizeof(EFI_DEVICE_PATH)); CopyMem(DiskDevicePath, Volume->DevicePath, PartialLength); CopyMem((UINT8 *)DiskDevicePath + PartialLength, EndDevicePath, sizeof(EFI_DEVICE_PATH)); - + // get the handle for that path RemainingDevicePath = DiskDevicePath; //Print(L" * looking at %s\n", DevicePathToStr(RemainingDevicePath)); Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &WholeDiskHandle); //Print(L" * remaining: %s\n", DevicePathToStr(RemainingDevicePath)); FreePool(DiskDevicePath); - + if (!EFI_ERROR(Status)) { //Print(L" - original handle: %08x - disk handle: %08x\n", (UINT32)DeviceHandle, (UINT32)WholeDiskHandle); - + // get the device path for later Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &DevicePathProtocol, (VOID **) &DiskDevicePath); if (!EFI_ERROR(Status)) { Volume->WholeDiskDevicePath = DuplicateDevicePath(DiskDevicePath); } - + // look at the BlockIO protocol Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &BlockIoProtocol, (VOID **) &Volume->WholeDiskBlockIO); if (!EFI_ERROR(Status)) { - + // check the media block size if (Volume->WholeDiskBlockIO->Media->BlockSize == 2048) Volume->DiskKind = DISK_KIND_OPTICAL; - + } else { Volume->WholeDiskBlockIO = NULL; //CheckError(Status, L"from HandleProtocol"); @@ -557,10 +561,10 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume) } //else // CheckError(Status, L"from LocateDevicePath"); } - + DevicePath = NextDevicePath; } // while - + if (!Bootable) { #if REFIT_DEBUG > 0 if (Volume->HasBootCode) @@ -568,16 +572,16 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume) #endif Volume->HasBootCode = FALSE; } - + // default volume icon based on disk kind ScanVolumeDefaultIcon(Volume); - + // open the root directory of the volume Volume->RootDir = LibOpenRoot(Volume->DeviceHandle); if (Volume->RootDir == NULL) { return; } - + // get volume name FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir); if (FileSystemInfoPtr != NULL) { @@ -591,8 +595,11 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume) // - name derived from file system type or partition type // get custom volume icon if present - if (FileExists(Volume->RootDir, L".VolumeIcon.icns")) - Volume->VolBadgeImage = LoadIcns(Volume->RootDir, L".VolumeIcon.icns", 32); + if (FileExists(Volume->RootDir, VOLUME_BADGE_NAME)) + Volume->VolBadgeImage = LoadIcns(Volume->RootDir, VOLUME_BADGE_NAME, 32); + if (FileExists(Volume->RootDir, VOLUME_ICON_NAME)) { + Volume->VolIconImage = LoadIcns(Volume->RootDir, VOLUME_ICON_NAME, 128); + } } static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_INFO *MbrEntry) @@ -605,9 +612,9 @@ static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_I UINT8 SectorBuffer[512]; BOOLEAN Bootable; MBR_PARTITION_INFO *EMbrTable; - + ExtBase = MbrEntry->StartLBA; - + for (ExtCurrent = ExtBase; ExtCurrent; ExtCurrent = NextExtCurrent) { // read current EMBR Status = refit_call5_wrapper(WholeDiskVolume->BlockIO->ReadBlocks, @@ -619,7 +626,7 @@ static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_I if (*((UINT16 *)(SectorBuffer + 510)) != 0xaa55) break; EMbrTable = (MBR_PARTITION_INFO *)(SectorBuffer + 446); - + // scan logical partitions in this EMBR NextExtCurrent = 0; for (i = 0; i < 4; i++) { @@ -631,7 +638,7 @@ static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_I NextExtCurrent = ExtBase + EMbrTable[i].StartLBA; break; } else { - + // found a logical partition Volume = AllocateZeroPool(sizeof(REFIT_VOLUME)); Volume->DiskKind = WholeDiskVolume->DiskKind; @@ -641,16 +648,16 @@ static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_I Volume->BlockIO = WholeDiskVolume->BlockIO; Volume->BlockIOOffset = ExtCurrent + EMbrTable[i].StartLBA; Volume->WholeDiskBlockIO = WholeDiskVolume->BlockIO; - + Bootable = FALSE; ScanVolumeBootcode(Volume, &Bootable); if (!Bootable) Volume->HasBootCode = FALSE; - + ScanVolumeDefaultIcon(Volume); - + AddListElement((VOID ***) &Volumes, &VolumesCount, Volume); - + } } } @@ -696,7 +703,7 @@ VOID ScanVolumes(VOID) if (SelfVolume == NULL) Print(L"WARNING: SelfVolume not found"); - + // second pass: relate partitions and whole disk devices for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { Volume = Volumes[VolumeIndex]; @@ -732,7 +739,7 @@ VOID ScanVolumes(VOID) // check size if ((UINT64)(MbrTable[PartitionIndex].Size) != Volume->BlockIO->Media->LastBlock + 1) continue; - + // compare boot sector read through offset vs. directly Status = refit_call5_wrapper(Volume->BlockIO->ReadBlocks, Volume->BlockIO, Volume->BlockIO->Media->MediaId, @@ -751,9 +758,9 @@ VOID ScanVolumes(VOID) SectorSum += SectorBuffer1[i]; if (SectorSum < 1000) continue; - + // TODO: mark entry as non-bootable if it is an extended partition - + // now we're reasonably sure the association is correct... Volume->IsMbrPartition = TRUE; Volume->MbrPartitionIndex = PartitionIndex; @@ -761,11 +768,11 @@ VOID ScanVolumes(VOID) Volume->VolName = PoolPrint(L"Partition %d", PartitionIndex + 1); break; } - + FreePool(SectorBuffer1); FreePool(SectorBuffer2); } - + } } /* VOID ScanVolumes() */ @@ -773,15 +780,15 @@ static VOID UninitVolumes(VOID) { REFIT_VOLUME *Volume; UINTN VolumeIndex; - + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { Volume = Volumes[VolumeIndex]; - + if (Volume->RootDir != NULL) { refit_call1_wrapper(Volume->RootDir->Close, Volume->RootDir); Volume->RootDir = NULL; } - + Volume->DeviceHandle = NULL; Volume->BlockIO = NULL; Volume->WholeDiskBlockIO = NULL; @@ -795,15 +802,15 @@ VOID ReinitVolumes(VOID) UINTN VolumeIndex; EFI_DEVICE_PATH *RemainingDevicePath; EFI_HANDLE DeviceHandle, WholeDiskHandle; - + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { Volume = Volumes[VolumeIndex]; - + if (Volume->DevicePath != NULL) { // get the handle for that path RemainingDevicePath = Volume->DevicePath; Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &DeviceHandle); - + if (!EFI_ERROR(Status)) { Volume->DeviceHandle = DeviceHandle; @@ -855,15 +862,15 @@ EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, VOID *Buffer; UINTN LastBufferSize, BufferSize; INTN IterCount; - + for (;;) { - + // free pointer from last call if (*DirEntry != NULL) { FreePool(*DirEntry); *DirEntry = NULL; } - + // read next directory entry LastBufferSize = BufferSize = 256; Buffer = AllocatePool(BufferSize); @@ -886,16 +893,16 @@ EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, FreePool(Buffer); break; } - + // check for end of listing if (BufferSize == 0) { // end of directory listing FreePool(Buffer); break; } - + // entry is ready to be returned *DirEntry = (EFI_FILE_INFO *)Buffer; - + // filter results if (FilterMode == 1) { // only return directories if (((*DirEntry)->Attribute & EFI_FILE_DIRECTORY)) @@ -905,7 +912,7 @@ EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, break; } else // no filter or unknown filter -> return everything break; - + } return Status; } @@ -930,10 +937,10 @@ BOOLEAN DirIterNext(IN OUT REFIT_DIR_ITER *DirIter, IN UINTN FilterMode, IN CHAR FreePool(DirIter->LastFileInfo); DirIter->LastFileInfo = NULL; } - + if (EFI_ERROR(DirIter->LastStatus)) return FALSE; // stop iteration - + for (;;) { DirIter->LastStatus = DirNextEntry(DirIter->DirHandle, &(DirIter->LastFileInfo), FilterMode); if (EFI_ERROR(DirIter->LastStatus)) @@ -949,7 +956,7 @@ BOOLEAN DirIterNext(IN OUT REFIT_DIR_ITER *DirIter, IN UINTN FilterMode, IN CHAR } else break; } - + *DirEntry = DirIter->LastFileInfo; return TRUE; } @@ -1066,7 +1073,7 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) { if (Second != NULL) Length2 = StrLen(Second); NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2)); - NewString[0] = 0; + NewString[0] = L'\0'; if (NewString != NULL) { if (*First != NULL) { StrCat(NewString, *First); diff --git a/refind/main.c b/refind/main.c index ea16053..6959a05 100644 --- a/refind/main.c +++ b/refind/main.c @@ -83,7 +83,7 @@ static VOID AboutrEFInd(VOID) { if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.4.2"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.5"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith"); @@ -175,7 +175,7 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, if (ErrorInStep != NULL) *ErrorInStep = 3; } - + // re-open file handles ReinitRefitLib(); @@ -234,15 +234,16 @@ static CHAR16 * FindInitrd(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) { KernelVersion = FindNumbers(FileName); Path = FindPath(LoaderPath); + MergeStrings(&Path, L"\\", 0); // Add trailing backslash; necessary for root directory DirIterOpen(Volume->RootDir, Path, &DirIter); while ((DirIterNext(&DirIter, 2, L"init*", &DirEntry)) && (InitrdName == NULL)) { InitrdVersion = FindNumbers(DirEntry->FileName); if (KernelVersion != NULL) { if (StriCmp(InitrdVersion, KernelVersion) == 0) - InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName); + InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName); } else { if (InitrdVersion == NULL) - InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName); + InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName); } // if/else if (InitrdVersion != NULL) FreePool(InitrdVersion); @@ -521,17 +522,20 @@ static CHAR16 * GetMainLinuxOptions(IN CHAR16 * LoaderPath, IN REFIT_VOLUME *Vol // that will (with luck) work fairly automatically. VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) { CHAR16 IconFileName[256]; - CHAR16 *FileName, *OSIconName = NULL, *Temp; + CHAR16 *FileName, *PathOnly, *OSIconName = NULL, *Temp; CHAR16 ShortcutLetter = 0; FileName = Basename(LoaderPath); + PathOnly = FindPath(LoaderPath); // locate a custom icon for the loader StrCpy(IconFileName, LoaderPath); ReplaceExtension(IconFileName, L".icns"); if (FileExists(Volume->RootDir, IconFileName)) { Entry->me.Image = LoadIcns(Volume->RootDir, IconFileName, 128); - } // if + } else if ((StrLen(PathOnly) == 0) && (Volume->VolIconImage != NULL)) { + Entry->me.Image = Volume->VolIconImage; + } // icon matched to loader or volume Temp = FindLastDirName(LoaderPath); MergeStrings(&OSIconName, Temp, L','); @@ -552,6 +556,9 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME Entry->OSType = 'R'; ShortcutLetter = 'R'; } else if (StriCmp(LoaderPath, MACOSX_LOADER_PATH) == 0) { + if (Volume->VolIconImage != NULL) { // custom icon file found + Entry->me.Image = Volume->VolIconImage; + } MergeStrings(&OSIconName, L"mac", L','); Entry->UseGraphicsMode = TRUE; Entry->OSType = 'M'; @@ -581,6 +588,8 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME Entry->me.ShortcutLetter = ShortcutLetter; if (Entry->me.Image == NULL) Entry->me.Image = LoadOSIcon(OSIconName, L"unknown", FALSE); + if (PathOnly != NULL) + FreePool(PathOnly); } // VOID SetLoaderDefaults() // Add a specified EFI boot loader to the list, using automatic settings -- 2.39.2