diff -Nru refind-0.10.4/BUILDING.txt refind-0.11.2/BUILDING.txt --- refind-0.10.4/BUILDING.txt 2015-12-07 22:33:08.000000000 +0000 +++ refind-0.11.2/BUILDING.txt 2017-07-30 20:36:49.000000000 +0000 @@ -9,32 +9,35 @@ use a cross-compiler, it must use the same CPU type and bit depth as your EFI implementation. (Normally that means 64-bit X64.) If you don't normally run Linux, you can run it in a VirtualBox or similar virtual - machine. (I describe some unsupported non-Linux build options shortly.) + machine. (I describe some unsupported non-Linux build options later.) * A standard set of Linux development tools, based on GCC. (I've tried - using clang 3.4 under Ubuntu, with partial success. The main rEFInd + using Clang 3.4 under Ubuntu, with partial success. The main rEFInd binary, gptsync, and some drivers compile successfully; but only gptsync runs normally. The drivers I've tried and the main rEFInd binary crash.) * One of the following: - * The TianoCore EDK2 package - (http://sourceforge.net/projects/tianocore/). I initially used the - UDK2010 package and others in that series, but beginning with rEFInd - 0.8.2, I've been using UDK2014 - (http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=UDK2014). - All of the UDK are "frozen," rather than the main EDK2 development - branch, which is changing as the developers add features, fix bugs, and - so on. See below for TianoCore setup instructions. + * The TianoCore EDK2/UDK package (https://github.com/tianocore/edk2). This + toolkit is available in an unstable development version (EDK2) or in + "frozen" forms (UDK2010, UDK2014, and so on); however, the term "EDK2" + is often used in reference to the TianoCore toolkit generally. To + simplify matters, I officially support only one UDK version at any given + moment. Currently (rEFInd 0.10.9), rEFInd compiles with UDK2014; but a + UDK2017 release is expected soon, so I've been making changes in an + effort to make rEFInd compatible with this soon-to-be-released version. + See below for TianoCore setup instructions. * The GNU-EFI package (http://sourceforge.net/projects/gnu-efi/). You can install this from a package called "gnu-efi"; however, rEFInd relies on features that were added sometime between version 3.0s and 3.0u, so I - recommend using 3.0u (or conceivably later). You should check your - GNU-EFI version number; you may need to download the latest source - code, compile it, and install it locally. The Makefiles assume a - GNU-EFI package installed via a package manager. If you install from - source code, you may need to adjust those Makefiles' paths. + recommend using 3.0u or later. The latest versions of GNU-EFI have + abandoned the trailing letter and switched to a more traditional + additional number, as in 3.0.2. You should check your GNU-EFI version + number; you may need to download the latest source code, compile it, and + install it locally. The Makefiles assume a GNU-EFI package installed via + a package manager. If you install from source code, you may need to + adjust those Makefiles' paths. Of the two toolkits, I prefer to use TianoCore because it produces binaries that are about 5-30KiB smaller than those made by GNU-EFI, and I can easily @@ -47,23 +50,6 @@ the Ubuntu Personal Package Archive (PPA) mechanism don't yet support TianoCore. -It's possible to use a non-Linux platform to compile rEFInd. To the best of -my knowledge, the rEFInd code doesn't rely on anything Linux-specific in -its build requirements, and GNU-EFI's Sourceforge page indicates that it -works under Windows and OS X, too; however, my one attempt to compile -GNU-EFI under OS X failed. I've received one report that rEFInd compiles -successfully with Clang and the TianoCore toolkit under OS X by adding the -refind.inf file to a .dsc file that you use for your own projects. You can -find brief instructions here (note that this is not my documentation): - -https://github.com/snarez/refind-edk2 - -Under Windows, you would need to either create a project or Makefile for -your non-GCC compiler or use a GCC port, such as MinGW -(http://www.mingw.org). You'd probably need to adjust the Makefiles in the -latter case. A procedure similar to that used under OS X might work using -GCC or Microsoft's C compiler, but I haven't tested this. - Preparing Your Development Kit ============================== @@ -86,128 +72,227 @@ distribution packages for it in RPM, Debian package file, or other formats; you MUST install the kit from source code using its own unusual compilation procedure. The installation documentation also omits at least one step and -is a bit unclear about others. Here's how I installed the toolkit: - -1) Download UDK2014.SR1.UP1.P1 from - https://sourceforge.net/apps/mediawiki/tianocore/index.php?title=UDK2014. - Note that UDK2015 is now available, but I have not yet adapted rEFInd to - build with it. (UDK2015 has made changes that require matching changes - to rEFInd.) - -2) Type "mkdir /usr/local/UDK2014". You can use another directory, but the - rEFInd Makefile assumes this location. You'll need to edit the EDK2BASE - variable in the top-level Makefile if you install somewhere else. - -3) Type "cd /usr/local/UDK2014". - -4) Unzip the downloaded file (UDK2014.SR1.UP1.P1.Complete.MyWorkSpace.zip) - in the current directory (/usr/local/UDK2014). This creates a handful of - files, including a tarball and a couple of .zip files. +is a bit unclear about others. Here's how to install the toolkit (note that +you'll need to be root to do this in the specified location): -5) Type "unzip UDK2014.SR1.UP1.MyWorkSpace.zip". This extracts the - platform-neutral portion of the development kit. +1. Download UDK2014.SR1.UP1.P1 from + https://github.com/tianocore/tianocore.github.io/wiki/UDK2014-Releases or + UDK2017 from + https://github.com/tianocore/tianocore.github.io/wiki/UDK2017. If you + want to live on the "bleeding edge," you can use an EDK2 daily release + version from https://github.com/tianocore/edk2. This document describes + three distinct compilation methods for TianoCore, each of which has + compatibility problems with some architectures. Specifically, the "make + tiano" target fails with EDK2 and UDK2017 for all architectures; and the + "make edk2" and "build" procedures work with EDK2 and UDK2017 for all + architectures but require modifications of project files to work with + AARCH64. + +2. Preparation procedures deviate depending on which development kit you're + using. For UDK2014, follow these steps: + + A. Type "mkdir /usr/local/UDK2014". You can use another directory, but + the rEFInd Makefile assumes this location. You'll need to edit the + TIANOBASE variable in the top-level Makefile if you install somewhere + else. + + B. Type "cd /usr/local/UDK2014". + + C. Unzip the downloaded file + (UDK2014.SR1.UP1.P1.Complete.MyWorkSpace.zip) in the current directory + (/usr/local/UDK2014). This creates a handful of files, including a + tarball and a couple of .zip files. (If you use an EDK2 daily release, + you can skip ahead to step 8; EDK2 drops the multi-layered + zip-file/tarball approach. You'll need to drop the "MyWorkSpace" + directory component, though -- or create it yourself and move all your + files there.) + + D. Type "unzip UDK2014.SR1.UP1.MyWorkSpace.zip". This extracts the + platform-neutral portion of the development kit. + + E. Type "cd MyWorkSpace". + + F. Type "tar xvf ../BaseTools\(Unix\).tar". This extracts the + Linux/Unix-specific portions of the toolkit. + +3. If you're using UDK2017 or an EDK2 daily build, follow these steps: + + A. Type "cd /usr/local/". + + B. Unzip the downloaded file (edk2-vUDK2017.zip) in the current directory + (/usr/local), or use git to pull down the latest source code. This + creates a subdirectory tree called edk2-vUDK2017. -6) Type "cd MyWorkSpace". + C. Type "cd edk2-vUDK2017" to change into the extracted directory. -7) Type "tar xvf ../BaseTools\(Unix\).tar". This extracts the - Linux/Unix-specific portions of the toolkit. - -8) Follow the build instructions at - https://sourceforge.net/apps/mediawiki/tianocore/index.php?title=Using_EDK_II_with_Native_GCC_4.4; - however, a few changes are required, as detailed below.... - -9) Type "source edksetup.sh BaseTools". This sets up some environment +9. Type "source edksetup.sh BaseTools". This sets up some environment variables, so subsequent steps (NOT including compiling rEFInd or its drivers) must be typed in the shell you use for this step. -10) Edit Conf/target.txt and change the following: +10. Edit Conf/target.txt and change the following: - ACTIVE_PLATFORM = MdePkg/MdePkg.dsc - TARGET = RELEASE (DEBUG might work, but I've not tested it). - TARGET_ARCH = X64 (on x86-64; leave this as IA32 on x86 or change it to AARCH64 on ARM64). If you plan to build multiple architectures, you can set this to "IA32 X64" or some other combination. - - TOOL_CHAIN_TAG = GCC48 (or other value depending on your GCC version; + - TOOL_CHAIN_TAG = GCC49 (or other value depending on your GCC version; type "gcc -v" to learn your GCC version number). Note that support for the latest GCC version takes a while to make it into the TianoCore toolkit, so if you're using a very recent GCC, you may need to specify an earlier version and hope for the best or modify - Conf/target.txt, as described shortly. + Conf/tools_def.txt, as described shortly. + - MAX_CONCURRENT_THREAD_NUMBER = {#CPUs + 1}; set this to one more + than the number of CPUs in your computer to optimize build time + when using the "edk2" targets with UDK2017 or an EDK2 daily build. + This setting has no effect when using the "tiano" targets with + UDK2014. The TianoCore Makefiles read some of these variables from this file and use them when accessing directories, so be sure to type these entries in the case specified. -11) The documentation refers to editing Conf/tools_def.txt in addition to +11. The documentation refers to editing Conf/tools_def.txt in addition to Conf/target.txt, but doesn't specify what to change in Conf/tools_def.txt. I haven't found it necessary to make any changes in - Conf/tools_def.txt EXCEPT when using GCC 4.7 on a Fedora 17 system with - the original UDK2014. With this setup, GCC 4.7 was newer than the most - recent GCC that TianoCore supported at that time. With that setup, I - found it necessary to change the following line: - *_GCC46_X64_ASM_FLAGS = DEF(GCC46_ASM_FLAGS) -m64 -melf_x86_64 - to: - *_GCC46_X64_ASM_FLAGS = DEF(GCC46_ASM_FLAGS) -m64 - Something similar may be necessary if you're using a very recent - GCC or some other compiler. - -12) Type "make -C /usr/local/UDK2014/MyWorkSpace/BaseTools/Source/C". - (This step is not documented on the EDK Web page.) Note that this - requires the g++ compiler and UUID development libraries. - -13) Type "build" to build the main set of EDK2 files. This process is + Conf/tools_def.txt EXCEPT for two cases: + + * When using GCC 4.7 on a Fedora 17 system with the original UDK2014, + GCC 4.7 was newer than the most recent GCC that TianoCore supported at + that time. With that setup, I found it necessary to change the + following line: + *_GCC46_X64_ASM_FLAGS = DEF(GCC46_ASM_FLAGS) -m64 -melf_x86_64 + to: + *_GCC46_X64_ASM_FLAGS = DEF(GCC46_ASM_FLAGS) -m64 + Although GCC 4.7 and Fedora 17 are both ancient, something similar may + be necessary if you're using a very recent GCC or some other compiler. + + * When cross-compiling for ARM64 (AARCH64) on an x86-64 system, + I needed to edit various entries to point to the cross-compiler + rather than the usual compilers. For instance: + *_GCC49_AARCH64_CC_PATH = ENV(GCC49_AARCH64_PREFIX)gcc + to: + *_GCC49_AARCH64_CC_PATH = /usr/bin/aarch64-linux-gnu-gcc + Similar changes for other variables in the same block are necessary. + +12. Type "make -C BaseTools/Source/C". (This step is not documented on the + EDK Web page.) Note that this requires the g++ compiler and UUID + development libraries. + +13. Type "build" to build the main set of EDK2 files. This process is likely to take a few minutes. This step requires Python 2; if you have Python 3 installed, you may need to adjust the default python for this build (for instance, by typing "eselect python set python2.7" in Gentoo). If you installed in a location other than the one I've specified, you must -edit the EDK2BASE variable in the top-level Makefile in the rEFInd source +edit the TIANOBASE variable in the top-level Makefile in the rEFInd source package. Once the toolkit is installed, you can build the filesystem drivers or rEFInd, as described below. -Compiling rEFInd -================ +Compiling rEFInd the Unix/Linux Way +=================================== With your development system set up, you can compile rEFInd as follows: -1) Download and uncompress the rEFInd source code archive. (If you're +1. Download and uncompress the rEFInd source code archive. (If you're reading this file, you've probably already done this task.) -2) Open a Linux shell prompt +2. Open a Linux shell prompt -3) Change into the archive's main directory. You should see several files +3. Change into the archive's main directory. You should see several files including this BUILDING.txt file and several subdirectories such as "refind", "libeg", "mok", "filesystems", and "include". -4) Type "make" to build rEFInd. The Makefile checks for the TianoCore - toolkit and tries to use it if it's present. If both toolkits are - installed, you can specify the toolkit name -- "make gnuefi" to build - with GNU-EFI, or either "make tiano" to build with TianoCore. With any - luck, rEFInd will compile without error, leaving the "refind_ia32.efi", - "refind_x64.efi", or "refind_aa64.efi" file, depending on your platform, - in the "refind" subdirectory. This same step builds the +4. If you want to build with the TianoCore toolkit and you installed in + a location other than the one specified in "Preparing Your Development + Kit," you must edit Makefile in the main rEFInd directory: change the + TIANOBASE and/or EDK2BASE variables to point to your toolkit's location. + The TIANOBASE variable is used with the "tiano" target (which can be used + with UDK2014, but not later versions) and EDK2BASE is used with the + "edk2" target, which is useful with all versions of TianoCore, with some + caveats (described later). + +5. Type "make" to build rEFInd and gptsync, or "make fs" to build the + filesystem drivers. The Makefile checks for the TianoCore toolkit and + tries to use it if it's present. Additional "make" targets enable you to + fine-tune how rEFInd is built and what components are built, as described + shortly. With any luck, rEFInd will compile without error, leaving the + "refind_ia32.efi", "refind_x64.efi", or "refind_aa64.efi" file, depending + on your platform, in the "refind" subdirectory. This same step builds the "gptsync_ia32.efi", "gptsync_x64.efi", or "gptsync_aa64.efi" program - file, in the "gptsync" subdirectory. (When cross-compiling with - TianoCore, "gptsync_aa64.efi" is not built because the cross-compiler - failed for me. Since gptsync is likely to be useless on ARM64, this is - no great loss.) If you want to build IA32 binaries on an x86-64 (X64) - system, type "ARCH=ia32 make". Similarly, you can specify "ARCH=aarch64" - to cross-compile for ARM64. This works only if you're using the - TianoCore build kit, and only if you set TARGET_ARCH to the appropriate - value in target.txt when you set up the TianoCore toolkit. If you plan - to build multiple architectures, be sure to copy the .efi file for the - first build out of the refind subdirectory before building the second - architecture. - -5) The default build process does NOT build the filesystem drivers. If you - want to build them, you must type "make fs" in the main rEFInd source - directory. This command builds with the TianoCore toolkit if it's - available and with GNU-EFI if it's not. Alternatively, you can type - "make fs_gnuefi" to build with GNU-EFI or "make fs_tiano" to build with - TianoCore. (You can prepend "ARCH=ia32" or "ARCH=aarch64" to - cross-compile for those architectures, as when building the main rEFInd - binary.) The result is filesystem drivers in the filesystems - subdirectory, and also copies placed in the drivers_{arch} subdirectory. + file, in the "gptsync" subdirectory. If you want to build IA32 binaries + on an x86-64 (X64) system, type "ARCH=ia32 make". Similarly, you can + specify "ARCH=aarch64" to cross-compile for ARM64, but this works only if + you're using the TianoCore build kit, and only if you set up TianoCore + for cross-compiling. If you plan to build multiple architectures, be sure + to copy the .efi file for the first build out of the refind subdirectory + and type "make clean" before building the second architecture. + +The top-level rEFInd Makefile supports three toolchains, each of which +provides several options to compile a subset of rEFInd's programs. (Note +that I specify AMD64/x86-64/X64 filenames in the below for simplicity.) The +"make" targets are: + +* gnuefi -- This target builds refind_x64.efi and gptsync_x64.efi with + the GNU-EFI toolkit. +* gptsync_gnuefi -- This target builds just the gptsync.efi program + with the GNU-EFI toolkit. +* fs_gnuefi -- This target builds all the filesystem drivers with the + GNU-EFI toolkit. +* all_gnuefi -- This target builds everything (refind_x64.efi, + gptsync_x64.efi, and the filesystem drivers) with the GNU-EFI toolkit. +* tiano -- This target builds refind_x64.efi and gptsync_x64.efi with the + TianoCore toolkit by using custom Makefile rules, bypassing the TianoCore + toolkit's "build" command. The result is slightly faster compilation in a + more traditional Unix/Linux way; but the compilation rules are fragile and + work only with the UDK2014 toolkit. Also, the gptsync_x64.efi program + is not built on ARM64/AARCH64 because the build process fails. (As + hybrid MBRs are likely to be useless on this platform, the inability + to build gptsync_aa64.efi is no great loss.) +* gptsync_tiano -- This target works like the preceding one, but builds + only gptsync_x64.efi. +* fs_tiano -- This target works like the preceding two, but builds the + filesystem drivers. +* all_tiano -- This target builds refind_x64.efi, gptsync_x64.efi, and + the filesystem drivers using custom Makefile rules. +* edk2 -- Like the "tiano" target, this one builds with the TianoCore + toolkit; but it employs a build method more like that favored by + TianoCore. It relies on .dsc, .dec, and .inf files as well as the "build" + program that comes with TianoCore. This method works with UDK2014, + UDK2017, and the latest (as of July, 2017) EDK2 snapshot. It also works + under OS X, if TianoCore is properly prepared. One limitation is that + building with UDK2014 for ARM64/AARCH64 requires modifying the .inf files + to remove the reference to CompilerIntrinsicsLib. This build method is + also a little bit slower than the preceding ones, in part because + EVERYTHING is built; narrower targets simply copy fewer of the resulting + files from within the TianoCore directory tree. Note that this method, + unlike the preceding ones, requires WRITE access to the TianoCore build + tree, or at least to the Build and Conf subdirectories of that tree, as + well as to the root of the tree. (This method creates a symbolic link of + the main rEFInd directory into the root of the TianoCore tree, and the + build process creates a subdirectory called Build/Refind to hold temporary + files and the final .efi files. The "make" utility then copies these files + to the same locations used by the tiano and gnuefi targets.) +* gptsync_edk2 -- This target copies just the gptsync_x64.efi binary to its + final destination. +* fs_edk2 -- This target works like the "edk2" target, but copies only + the filesystem drivers to their destination. +* all_edk2 -- This target builds and copies everything using the + TianoCore-style build process. +* all -- This is the default target. It runs the "edk2" target if + the EDK2BASE variable points to a valid TianoCore toolkit. If not, it runs + the "tiano" target if the TIANOBASE variable points to a valid TianoCore + toolkit. If neither of these variables points to a valid TianoCore + toolkit, the "gnuefi" target is tried. +* gptsync -- This target builds the gptsync_x64.efi program using the + same precedence for toolkits as the "all" target. +* fs -- This target builds the filesystem drivers using the same precedence + for toolkits as the "all" target. +* clean -- This target deletes intermediate build files. Note that it + deletes intermediate files generated by ALL the build methods (gnuefi, + tiano, and edk2). +* install -- This target runs the refind-install script with no + arguments. If rEFInd doesn't compile correctly, you'll need to track down the source of the problem. Double-check that you've got all the necessary development @@ -224,36 +309,138 @@ EFILIB = /usr/lib EFICRT0 = /usr/lib -If you've installed GNU-EFI from source code, you may need to add "local" -to those paths, as in "/usr/local/include/efi". You might need to change +If you've installed GNU-EFI from source code, you may need to add "local" to +those paths, as in "/usr/local/include/efi". You might need to change references to "lib" to "lib32" or "lib64" on some systems. Recall that you -need at least GNU-EFI version 3.0l to build rEFInd, and until very -recently, most distributions provided out-of-date versions of this package. +need at least GNU-EFI version 3.0u to build rEFInd, and some older or +behind-the-times distributions might provide out-of-date versions of this +package. If you're using TianoCore's EDK2, as noted earlier, you may need to adjust -the EDK2BASE variable in Makefile. +the TIANOBASE or EDKBASE variable in Makefile. -When I tried to compile rEFInd under Ubuntu 12.04 (i386) using GNU-EFI, -even with a locally-compiled GNU-EFI 3.0p or 3.0q, I got errors like this: -main.o: In function `StartLegacy.isra.0': -main.c:(.text+0x8b1): undefined reference to `__stack_chk_fail_local' -lib.o: In function `ScanVolumeBootcode.part.3': -lib.c:(.text+0xf2f): undefined reference to `__stack_chk_fail_local' -lib.o: In function `ScanExtendedPartition.isra.4': +Compiling rEFInd the TianoCore Way +================================== -The solution was to recompile GNU-EFI with the -fno-stack-protector GCC -flag. In GNU-EFI, this can be added to the CFLAGS line in Make.defaults. +If you use TianoCore, you may know that the standard way to build +applications under that environment does not follow the typical Unix/Linux +development model described above. Instead, the application to be compiled +is dropped into the main TianoCore source tree and compiled there using the +"build" command. rEFInd can be compiled in this way. I am providing +instructions on compiling in this way because it may work better than +rEFInd's Makefiles in some cases, especially if you're using a non-Linux +platform for development. I've successfully compiled rEFInd 0.10.8 under OS +X in this way. (I present details and caveats shortly.) Note that the "edk2" +and related Makefile targets use this method behind the scenes. The +procedure is: + +1. Download and prepare the TianoCore toolkit, as described earlier, + under "Preparing Your Development Kit." Note that you will have to adjust + this procedure if you're using a non-Linux OS. + +2. Change to the directory that holds the BaseTools, MdePkg, ShellPkg, and + other directories and files. If you use the UDK2014.SR1.UP1.P1 package + noted earlier, this would be the MyWorkSpace directory. + +3. Unpack the rEFInd source tarball in the current directory. + +4. Rename the rEFInd directory (refind-{version}, where {version} is the + version number) to RefindPkg. Alternatively, create a symbolic link + called RefindPkg that points to the real directory. + +5. Type "source edksetup.sh BaseTools". (You can skip this step if you're + using the same login session you used to build the TianoCore toolkit; you + need to type this command only if you've logged out and back in again, + are using a different window from the one you used to build TianoCore, or + have otherwise modified the environment variables set in edksetup.sh.) + +6. If you're using UDK2014 AND you're compiling for AARCH64, you must + open refind.inf, gptsync.inf, and the .inf files for all the drivers in + the filesystems subdirectory and comment out the line that reads + "CompilerIntrinsicsLib". This library is needed for later versions of + EDK2 but is not present in (and not required for) UDK2014. + +7. Type "build -p RefindPkg/RefindPkg.dsc" to build rEFInd. If you've + properly configured your TianoCore installation for cross-compiling, you + may add "-a {ARCH}", where {ARCH} is an architecture code, to compile for + that platform. For instance, "build -a IA32 -p RefindPkg/RefindPkg.dsc" + builds for IA32 (32-bit x86), even on another type of computer. + +The rEFInd package should build, leaving binaries buried ridiculously deep +within the directory tree. For instance, on my test build, the rEFInd +binaries were at: + +Build/Refind/RELEASE_GCC49/X64/btrfs.efi +Build/Refind/RELEASE_GCC49/X64/ext2.efi +Build/Refind/RELEASE_GCC49/X64/ext4.efi +Build/Refind/RELEASE_GCC49/X64/gptsync.efi +Build/Refind/RELEASE_GCC49/X64/hfs.efi +Build/Refind/RELEASE_GCC49/X64/iso9660.efi +Build/Refind/RELEASE_GCC49/X64/ntfs.efi +Build/Refind/RELEASE_GCC49/X64/refind.efi +Build/Refind/RELEASE_GCC49/X64/reiserfs.efi + +I've tested this procedure under Ubuntu 16.04 with GCC 5.4.0 and under OS X +10.11 with both Clang 7.0.0/XCode 7.1.1 and Clang 8.0.0/XCode 8.1.1. (See +below for Mac caveats.) In theory, it might work under Windows, but if you +use anything but a GCC- or Clang-derived compiler, there's a good chance +you'll run into a compiler-specific code incompatibility. + + +Compiling rEFInd Under OS X +=========================== + +Building under OS X is *NOT SUPPORTED.* I've tested this procedure and it +seems to work in minimal testing. My build under OS X required several +changes for compilation to succeed: + +* A relatively recent TianoCore EDK2 from the TianoCore git repository + is required; the stable UDK2014 and UDK2015 DO NOT work. I have yet to + test with the final release of UDK2017, but I expect it should work. + +* Setting up the Mac development environment required following instructions + at https://github.com/tianocore/tianocore.github.io/wiki/Xcode, with the + caveat that the UnixPkg directory described there is essentially empty; + instead, I compiled the BaseTools/Source/C code, as described earlier. (I + don't know if this was strictly necessary, but the tools did compile, + despite several warnings.) I also skipped installing QEMU. + +* Instead of "TOOL_CHAIN_TAG = GCC49", I set "TOOL_CHAIN_TAG = XCODE5" in + Conf/target.txt. + +* I had to edit Conf/tools_def.txt and edit the RELEASE_XCODE5_X64_CC_FLAGS + line to remove the "-Werror" option. With this option set, the main rEFInd + binary and several drivers failed to build. **CAUTION:** The warnings that + prevented the rEFInd binary from compiling with "-Werror" intact related + to ((sysv_abi)) declarations in mok/mok.h. This makes me think that the + resulting binary may be incompatible with Shim, although I've not tested + this; my only testing of the binary built under OS X were on systems with + Secure Boot disabled or with the Secure Boot system under my complete + control and without Shim installed. + +* I had to edit refind.inf and uncomment the line in the Packages section + that reads "StdLib/StdLib.dec". + +* I've been unable to get the Btrfs driver to build. To adjust the package + to omit this driver, edit the RefindPkg.dsc file and remove the line near + the bottom that reads "RefindPkg/filesystems/btrfs.inf". + +Note that if you want to use macOS or Windows to compile rEFInd, you might +be able to create a project or Makefile for your non-GCC compiler or use a +GCC port, such as MinGW (http://www.mingw.org), along with the procedure +described earlier, under "Compiling rEFInd the Unix/Linux Way." You'd +probably need to adjust the Makefiles in the latter case. Installing rEFInd ================= With rEFInd compiled, you can install it. The easiest way to do this is -with the refind-install script, which works on both Linux and Mac OS X. +with the refind-install script, which works on both Linux and macOS. Alternatively, you can type "make install" to install using this script. Note that this script copies files to the ESP and uses "efibootmgr" (on -Linux) or "bless" (on OS X) to add rEFInd to the firmware's boot loader +Linux) or "bless" (on macOS) to add rEFInd to the firmware's boot loader list. The docs/man/refind-install.8 file (and its HTML conversion, docs/refind/refind-install.html) provides more details on this script and its use. @@ -279,40 +466,17 @@ The refind-install script, and therefore the "install" target in the Makefile, installs the program directly to the ESP and it modifies the *CURRENT COMPUTER's* NVRAM. Thus, you should *NOT* use this target as part -of the build process for your binary packages (RPMs, Debian packages, -etc.). (Gentoo could use it in an ebuild, though....) You COULD, however, -install the files to a directory somewhere (/usr/share/refind or whatever) -and then call refind-install as part of the binary package installation -process. Placing the files directly in /boot/efi/EFI/{distname}/refind and -then having a post-install script call efibootmgr is probably the better -way to go, but this assumes that the ESP is mounted at /boot/efi. - - -Compiling the EFI Filesystem Drivers -==================================== - -To build all the drivers, you can type "make fs", "make fs_tiano", or "make -fs_gnuefi" from the main directory, which builds the drivers and places -copies in both the filesystems and drivers_{arch} subdirectories. - -To install drivers, you can type "make install" in the "filesystems" -directory. This copies all the drivers to the -"/boot/efi/EFI/refind/drivers" directory. Alternatively, you can copy the -files you want manually. The refind-install script includes an optional -"--drivers" option that will install the drivers along with the main rEFInd -program, but to the drivers_{arch} subdirectory of the main rEFInd -installation directory. - -*CAUTION:* Install drivers for your system's architecture *ONLY*. -Installing drivers for the wrong architecture causes some systems to hang -at boot time. This risk can be minimized by including the architecture code -in the drivers subdirectory name (drivers_x64 or drivers_ia32). - -The drivers all rely on filesystem wrapper code created by rEFIt's author, -Christoph Pfisterer. Most of the drivers seem to have passed through -Oracle's VirtualBox project (https://www.virtualbox.org) and the Clover -boot loader project (https://sourceforge.net/projects/cloverefiboot/), -which I used as the source for this build. +of the build process for your binary packages (RPMs, Debian packages, etc.). +(Gentoo could use it in an ebuild, though....) You COULD, however, install +the files to a directory somewhere (/usr/share/refind or whatever) and then +call refind-install as part of the binary package installation process. +Placing the files directly in /boot/efi/EFI/{distname}/refind and then +having a post-install script call efibootmgr could also work, but this +assumes that the ESP is mounted at /boot/efi. Also, Debian packages try to +create symbolic links when updating packages, which won't work on an ESP, +which should use FAT. For packaging examples, see the refind.spec file and +debian subdirectory of the rEFInd source tarball. + Adding Support for Network Boot =============================== diff -Nru refind-0.10.4/CREDITS.txt refind-0.11.2/CREDITS.txt --- refind-0.10.4/CREDITS.txt 2016-09-29 18:24:17.000000000 +0000 +++ refind-0.11.2/CREDITS.txt 2017-08-08 01:17:11.000000000 +0000 @@ -3,8 +3,8 @@ program, both in its original version (rEFIt) and by providing features I've incorporated into the current version. Specifically: -Program (C source code) files: ------------------------------- +Program (C source code and script) files: +----------------------------------------- * Christoph Pfisterer was the original author of rEFIt. See its Web page, http://refit.sourceforge.net, for this version of the program. Christoph @@ -36,6 +36,9 @@ * John Bressler (jrb1327@gmail.com) contributed the code to boot BIOS-based OSes on UEFI-based PCs. +* CJ Vaughter contributed the code for support of touch displays and mice, + with some improvements to the former by Tom Briden. + * The code for editing boot options (cursor_left(), cursor_right(), and line_edit() in screen.c) is taken from gummiboot (http://freedesktop.org/wiki/Software/gummiboot). @@ -74,6 +77,13 @@ Vandevenne. (The libeg/lodepng_xtra.c file provides some necessary ancillary and interface functions written by me.) +* Pavel Penev contributed the code to enable encrypting rEFInd's locally + generated signing keys in refind-install. + +* The RefindPkg.dec and RefindPkg.dsc files, used to enable compiling + rEFInd in the traditional TianoCore way, come from + https://github.com/snarez/refind-edk2. + Icons and graphics: ------------------- diff -Nru refind-0.10.4/debian/changelog refind-0.11.2/debian/changelog --- refind-0.10.4/debian/changelog 2016-10-10 23:12:05.000000000 +0000 +++ refind-0.11.2/debian/changelog 2017-12-04 23:39:01.000000000 +0000 @@ -1,3 +1,10 @@ +refind (0.11.2-1) unstable; urgency=medium + + * Update to 0.11.2 upstream release + - see http://www.rodsbooks.com/refind/revisions.html for changes + + -- Tianon Gravi Mon, 04 Dec 2017 15:39:01 -0800 + refind (0.10.4-1) unstable; urgency=medium * Update to 0.10.4 upstream release diff -Nru refind-0.10.4/debian/copyright refind-0.11.2/debian/copyright --- refind-0.10.4/debian/copyright 2016-06-18 05:19:13.000000000 +0000 +++ refind-0.11.2/debian/copyright 2017-12-04 21:52:17.000000000 +0000 @@ -5,7 +5,7 @@ Files: * Copyright: 2006 Christoph Pfisterer - 2012-2016 Roderick W. Smith + 2012-2017 Roderick W. Smith License: BSD-3-clause and GPL-3+ Files: debian/* @@ -56,7 +56,7 @@ libeg/image.c libeg/screen.c Copyright: 2006-2010 Christoph Pfisterer - 2012-2016 Roderick W. Smith + 2012-2017 Roderick W. Smith License: BSD-3-clause and GPL-3+ Files: refind/icns.c @@ -69,6 +69,10 @@ Copyright: 2014-2015 Roderick W. Smith License: GPL-3+ +Files: refind/pointer.[ch] +Copyright: 2017 CJ Vaughter +License: GPL-3+ + Files: refind/crc32.[ch] Copyright: 1986 Gary S. Brown License: unrestricted-crc32 @@ -131,6 +135,7 @@ License: BSD-3-clause Files: include/tiano_includes.h + include/version.h Copyright: 2012 Roderick W. Smith License: GPL-3+ @@ -327,6 +332,7 @@ Files: icons/boot_win.png icons/func_csr_rotate.png + icons/mouse.png icons/os_clover.png icons/os_freebsd.png icons/os_gummiboot.png @@ -344,17 +350,34 @@ icons/tool_rescue.png icons/transparent.png icons/README -Copyright: 2015 by Roderick W. Smith +Copyright: 2015-2017 by Roderick W. Smith License: LGPL-3+ or CC-BY-SA-3.0 +Files: icons/os_trusty.png + icons/os_xenial.png + icons/os_zesty.png + icons/svg/os_xenial.png + icons/svg/os_zesty.png +Copyright: 2014-2017 by Canonical Ltd. +License: CC-BY-SA-3.0 + Files: icons/os_debian.png Copyright: 1999 by Debian Project License: LGPL-3+ or CC-BY-SA-3.0 +Files: icons/os_devuan.png +Copyright: 2017 by Dyne.org foundation +License: CC-BY-SA-4.0 + Files: icons/os_elementary.png Copyright: 2008 Dan Rabbit License: GPL-2 +Files: icons/os_void.png +License: public-domain + Claimed as public domain by source + (https://commons.wikimedia.org/wiki/File:Void_Linux_logo.svg) + Files: icons/svg/* Copyright: 2015 by Roderick W. Smith License: LGPL-3+ or CC-BY-SA-3.0 @@ -363,6 +386,10 @@ Copyright: 1999 by Debian Project License: LGPL-3+ or CC-BY-SA-3.0 +Files: icons/svg/os_devuan.svg +Copyright: 2017 by Dyne.org foundation +License: CC-BY-SA-4.0 + Files: icons/svg/os_elementary.svg Copyright: 2008 Dan Rabbit License: GPL-2 @@ -410,7 +437,7 @@ Files: docs/* */README* -Copyright: 2012-2016 Roderick W. Smith +Copyright: 2012-2017 Roderick W. Smith License: GFDL-1.3 License: BSD-2-clause diff -Nru refind-0.10.4/debian/postinst refind-0.11.2/debian/postinst --- refind-0.10.4/debian/postinst 2016-06-18 02:09:12.000000000 +0000 +++ refind-0.11.2/debian/postinst 2017-12-04 23:33:48.000000000 +0000 @@ -12,7 +12,7 @@ # Remove any existing NVRAM entry for rEFInd, to avoid creating a duplicate. ExistingEntry=`efibootmgr | grep "rEFInd Boot Manager" | cut -c 5-8` if [[ -n $ExistingEntry ]] ; then - efibootmgr --bootnum $ExistingEntry --delete-bootnum &> /dev/null + efibootmgr --bootnum $ExistingEntry --delete-bootnum > /dev/null fi cd /usr/share/refind @@ -47,7 +47,11 @@ ./refind-install --shim $ShimFile --yes > /dev/null fi else - ./refind-install --yes > /dev/null + if [[ -n $SBSign && -n $OpenSSL ]] ; then + ./refind-install --localkeys --yes > /dev/null + else + ./refind-install --yes > /dev/null + fi fi } # install_to_esp() diff -Nru refind-0.10.4/docs/man/mkrlconf.8 refind-0.11.2/docs/man/mkrlconf.8 --- refind-0.10.4/docs/man/mkrlconf.8 2016-10-09 23:12:00.000000000 +0000 +++ refind-0.11.2/docs/man/mkrlconf.8 2017-10-22 20:36:49.000000000 +0000 @@ -1,7 +1,7 @@ -.\" Copyright 2015-2016 Roderick W. Smith (rodsmith@rodsbooks.com) +.\" Copyright 2015-2017 Roderick W. Smith (rodsmith@rodsbooks.com) .\" May be distributed under the GNU Free Documentation License version 1.3 or any later version -.TH "MKRLCONF" "8" "0.10.4" "Roderick W. Smith" "rEFInd Manual" +.TH "MKRLCONF" "8" "0.11.2" "Roderick W. Smith" "rEFInd Manual" .SH "NAME" mkrlconf \- Create a Linux kernel configuration file for rEFInd .SH "SYNOPSIS" diff -Nru refind-0.10.4/docs/man/mvrefind.8 refind-0.11.2/docs/man/mvrefind.8 --- refind-0.10.4/docs/man/mvrefind.8 2016-10-09 23:11:54.000000000 +0000 +++ refind-0.11.2/docs/man/mvrefind.8 2017-10-22 20:36:47.000000000 +0000 @@ -1,7 +1,7 @@ -.\" Copyright 2015-2016 Roderick W. Smith (rodsmith@rodsbooks.com) +.\" Copyright 2015-2017 Roderick W. Smith (rodsmith@rodsbooks.com) .\" May be distributed under the GNU Free Documentation License version 1.3 or any later version -.TH "MVREFIND" "8" "0.10.4" "Roderick W. Smith" "rEFInd Manual" +.TH "MVREFIND" "8" "0.11.2" "Roderick W. Smith" "rEFInd Manual" .SH "NAME" mvrefind \- Move a rEFInd installation from one location to another .SH "SYNOPSIS" diff -Nru refind-0.10.4/docs/man/refind-install.8 refind-0.11.2/docs/man/refind-install.8 --- refind-0.10.4/docs/man/refind-install.8 2016-10-09 23:11:49.000000000 +0000 +++ refind-0.11.2/docs/man/refind-install.8 2017-10-22 20:36:44.000000000 +0000 @@ -1,14 +1,14 @@ -.\" Copyright 2015-2016 Roderick W. Smith (rodsmith@rodsbooks.com) +.\" Copyright 2015-2017 Roderick W. Smith (rodsmith@rodsbooks.com) .\" May be distributed under the GNU Free Documentation License version 1.3 or any later version -.TH "REFIND-INSTALL" "8" "0.10.4" "Roderick W. Smith" "rEFInd Manual" +.TH "REFIND-INSTALL" "8" "0.11.2" "Roderick W. Smith" "rEFInd Manual" .SH "NAME" refind-install \- Install rEFInd to the ESP and create an NVRAM entry .SH "SYNOPSIS" .BI "refind-install " [--notesp | --usedefault \fIdevice-file\fR | --root \fImount-point\fR | --ownhfs \fIdevice-file\fR ] [--keepname] [--nodrivers | --alldrivers] -[--shim \fIshim-filename\fR] [--localkeys] [--yes] +[--shim \fIshim-filename\fR] [--localkeys] [--encryptkeys] [--yes] .SH "DESCRIPTION" @@ -233,6 +233,20 @@ not, so this option is not the default. .TP +.B \-\-encryptkeys +Ordinarily, if you use the \-\-localkeys option, \fBrefind\-install\fR +stores the local key files on your hard disk in an unencrypted form. Thus, +should your computer be compromised, the intruder could use your own key to +sign a modified boot loader, eliminating the benefits of Secure Boot. If you +use this option, then the private key is stored in an encrypted form, +secured via an encryption password. You must enter this password before the +key can be used to sign any binary, thus reducing the risk that an intruder +could hijack your boot process. This is obviously a highly desirable option, +but the downside is that you must remember the password and enter it +whenever you update rEFInd or any other program signed with your private +key. This also makes a fully automated update of rEFInd impossible. + +.TP .B \-\-keepname This option is useful only in conjunction with \-\-shim. It tells \fBrefind\-install\fR to keep rEFInd's regular filename (typically diff -Nru refind-0.10.4/docs/man/refind-mkdefault.8 refind-0.11.2/docs/man/refind-mkdefault.8 --- refind-0.10.4/docs/man/refind-mkdefault.8 2016-10-09 23:11:44.000000000 +0000 +++ refind-0.11.2/docs/man/refind-mkdefault.8 2017-10-22 20:36:42.000000000 +0000 @@ -1,7 +1,7 @@ -.\" Copyright 2016 Roderick W. Smith (rodsmith@rodsbooks.com) +.\" Copyright 2016-2017 Roderick W. Smith (rodsmith@rodsbooks.com) .\" May be distributed under the GNU Free Documentation License version 1.3 or any later version -.TH "REFIND-MKDEFAULT" "8" "0.10.4" "Roderick W. Smith" "rEFInd Manual" +.TH "REFIND-MKDEFAULT" "8" "0.11.2" "Roderick W. Smith" "rEFInd Manual" .SH "NAME" refind-mkdefault \- Set rEFInd as the default EFI boot option .SH "SYNOPSIS" Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/docs/refind/ambience.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/docs/refind/ambience.png differ diff -Nru refind-0.10.4/docs/refind/bootcoup.html refind-0.11.2/docs/refind/bootcoup.html --- refind-0.10.4/docs/refind/bootcoup.html 2016-10-09 17:09:50.000000000 +0000 +++ refind-0.11.2/docs/refind/bootcoup.html 2017-10-22 20:13:03.000000000 +0000 @@ -16,7 +16,8 @@

by Roderick W. Smith, rodsmith@rodsbooks.com

-

Originally written: 10/9/2016, referencing rEFInd 0.10.4

+

Originally written: 4/24/2016; last Web page update: +10/22/2017, referencing rEFInd 0.11.2

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!

@@ -153,7 +154,7 @@ -
  • Recovering from a Coup Using OS X +
  • Recovering from a Coup Using MacOS @@ -193,9 +196,9 @@

    Evading the Guards: Performing a One-Time Boot to Your Desired OS

    -

    Most EFIs provide their own build-in boot managers. These tools are primitive, and in some cases they can be difficult to reach, but they can be useful if you need to bypass a new system default in order to boot an OS that has the tools you need to control the boot process.

    +

    Most EFIs provide their own built-in boot managers. These tools are primitive, and in some cases they can be difficult to reach, but they can be useful if you need to bypass a new system default in order to boot an OS that has the tools you need to control the boot process.

    -

    On Macs, holding the Option key (or Alt with a PC keyboard) brings up the Mac's boot manager. Typically, the Esc key, Enter key, or a function key (usually F8 or above) does the job on UEFI-based PCs. Some computers provide a prompt for what key to use to access the boot menu, but this isn't always true. Sometimes the keyboard is disabled in the early stages of the boot process by default—part of a strategy to speed up system boots. Disabling a "fast start" feature in the firmware may work around this problem. Getting into the firmware can be a challenge on such computers, though. Microsoft provides a way to do this in Windows 8 and later; see this How-To Geek article for documentation on how to use this feature.

    +

    On Macs, holding the Option key (or Alt with a PC keyboard) brings up the Mac's boot manager. Typically, the Esc key, Enter key, or a function key (usually F8 or above) does the job on UEFI-based PCs. Some computers provide a prompt for what key to use to access the boot menu, but this isn't always true. Sometimes the keyboard is disabled in the early stages of the boot process by default—part of a strategy to speed up system boots. Disabling a "fast start" feature in the firmware may work around this problem. Getting into the firmware can be a challenge on such computers, though. Microsoft provides a way to do this in Windows 8 and later; see this How-To Geek article for documentation on how to use this feature. If a Linux distribution uses the popular systemd initialization system, you can type systemctl reboot --firmware as root (or using sudo) to do the same from Linux.

    Once you've found the built-in boot manager, you'll see its display, which is typically a text-mode listing of boot options. On UEFI-based PCs, the user interface is typically similar to the one used in years past on BIOS-based computers to select the boot device; it's simply been upgraded to include the descriptions held in NVRAM for specific boot loaders. (In fact, prompts are often outdated and misleading; as in the below example, they may refer to "boot devices," when in fact most of the options are EFI boot loader programs, not hardware devices.) As an example, an ASUS P8 H77-I's boot manager looks like this:

    @@ -211,7 +214,7 @@

    Staging a Counter-Revolution: Re-Installing rEFInd

    -

    The most general, and in some cases the easiest, solution to a boot coup is to re-install rEFInd. If you haven't updated rEFInd in a while, this approach has the advantage of providing an update to rEFInd (assuming you first download the latest version). The Installing rEFInd page describes how to install rEFInd from Linux, OS X, Windows, or an EFI shell. The refind-install script preserves your existing refind.conf configuration file, so an upgrade should not affect your customizations. (The rEFInd icons will be updated to the latest versions, but refind-install moves the original icons to a backup directory, so you can restore them if you've customized them or if they've changed and you don't like the new icons.)

    +

    The most general, and in some cases the easiest, solution to a boot coup is to re-install rEFInd. If you haven't updated rEFInd in a while, this approach has the advantage of providing an update to rEFInd (assuming you first download the latest version). The Installing rEFInd page describes how to install rEFInd from Linux, macOS, Windows, or an EFI shell. The refind-install script preserves your existing refind.conf configuration file, so an upgrade should not affect your customizations. (The rEFInd icons will be updated to the latest versions, but refind-install moves the original icons to a backup directory, so you can restore them if you've customized them or if they've changed and you don't like the new icons.)

    One possible complication to this approach is if you're stuck booting in an unfamiliar OS. In such a case, you may be able to boot into your preferred OS on a one-time basis by using your computer's built-in boot manager, as described in the previous section. The trouble is that how you do this varies greatly from one computer to another.

    @@ -318,16 +321,16 @@

    You can achieve a similar result in Fedora by installing the yum-plugin-versionlock package, ensuring that enabled = 1 is set in /etc/yum/pluginconf.d/versionlock.conf, and editing /etc/yum/pluginconf.d/versionlock.list to include the names and versions of packages you want to lock at a particular version.

    -

    Recovering from a Coup Using OS X

    +

    Recovering from a Coup Using MacOS

    -

    A boot coup that leaves a computer booting straight to OS X was most likely caused by an update to OS X—either a software update that installed a fresh copy of the OS X boot loader or a complete re-installation of the OS. In either event, the solution is conceptually similar to the Linux solution, but the tools you use to correct the problem differ. In OS X, you would either use Startup Disk to set rEFInd as the default or use bless to do the same.

    +

    A boot coup that leaves a computer booting straight to macOS was most likely caused by an update to macOS—either a software update that installed a fresh copy of the macOS boot loader or a complete re-installation of the OS. In either event, the solution is conceptually similar to the Linux solution, but the tools you use to correct the problem differ. In macOS, you would either use Startup Disk to set rEFInd as the default or use bless to do the same.

    Using Startup Disk to Adjust Your Boot Priority

    -

    The Startup Disk utility appears in the System Preferences tool. Unfortunately, it will likely be useless if you installed rEFInd using refind-install and its default options, since Startup Disk is designed to switch between OS X installations; it's not smart enough to detect a rEFInd installation and re-activate it.

    +

    The Startup Disk utility appears in the System Preferences tool. Unfortunately, it will likely be useless if you installed rEFInd using refind-install and its default options, since Startup Disk is designed to switch between macOS installations; it's not smart enough to detect a rEFInd installation and re-activate it.

    If, however, you installed rEFInd by using the --ownhfs option to refind-install, your rEFInd installation volume should show up as an option in the Startup Disk utility. You should be able to click on it and then click Restart. Note that the name of the rEFInd volume may not be rEFInd, as it is in this screen shot; the name will match whatever volume holds rEFInd on your computer.

    @@ -335,13 +338,13 @@ height="402" alt="Startup Disk may enable you to reset rEFInd to being the default boot program." border=2>
    -

    As with most of the fixes described on this page, this method of recovering from a boot coup will not protect you from future boot coups. Fortunately, OS X updates that create boot coups are fairly rare, but you'll have to resign yourself to the fact that the problem may recur in the future.

    +

    As with most of the fixes described on this page, this method of recovering from a boot coup will not protect you from future boot coups. Fortunately, macOS updates that create boot coups are fairly rare, but you'll have to resign yourself to the fact that the problem may recur in the future.

    Using bless to Adjust Your Boot Priority

    -

    The more general solution to resetting rEFInd as the default boot manager from OS X is to follow a subset of the manual OS X installation instructions. Unfortunately, some details depend on where it is installed—on the ESP, on the main OS X root (/) partition, or on a separate HFS+ volume. If rEFInd is installed on its own HFS+ partition, using Startup Disk, as described in the previous section, is likely to be the easier solution. For the other two options, you should first figure out where rEFInd is installed and then follow this procedure:

    +

    The more general solution to resetting rEFInd as the default boot manager from macOS is to follow a subset of the manual macOS installation instructions. Unfortunately, some details depend on where rEFInd is installed—on the ESP, on the main macOS root (/) partition, or on a separate HFS+ volume. If rEFInd is installed on its own HFS+ partition, using Startup Disk, as described in the previous section, is likely to be the easier solution. For the other two options, you should first figure out where rEFInd is installed and then follow this procedure:

      @@ -378,7 +381,7 @@

      One major caveat is that the bless command will fail if System Integrity Protection (SIP) is active. This feature is part of OS X 10.11 (El Capitan) and later, and you will have dealt with it during rEFInd installation if it's active. See this page of the rEFInd documentation for more on this subject. You can use any of the procedures outlined there with reference to installing rEFInd for dealing with a boot coup, as well.

      -

      As with most of the fixes described on this page, this method of recovering from a boot coup will not protect you from future boot coups. Fortunately, OS X updates that create boot coups are fairly rare, but you'll have to resign yourself to the fact that the problem may recur in the future.

      +

      As with most of the fixes described on this page, this method of recovering from a boot coup will not protect you from future boot coups. Fortunately, macOS updates that create boot coups are fairly rare, but you'll have to resign yourself to the fact that the problem may recur in the future.

      Recovering from a Coup Using Windows

      @@ -410,7 +413,7 @@
    -

    Note that EasyUEFI's menu shows the names of the boot entries. In some cases, rEFInd may be registered under another name. This is particularly likely if you used OS X's bless or Windows' bcdedit tools to register rEFInd with the firmware. You may be able to locate the rEFInd binary by examining the File path entry in the Detailed information pane, after selecting a "candidate" entry.

    +

    Note that EasyUEFI's menu shows the names of the boot entries. In some cases, rEFInd may be registered under another name. This is particularly likely if you used macOS's bless or Windows' bcdedit tools to register rEFInd with the firmware. You may be able to locate the rEFInd binary by examining the File path entry in the Detailed information pane, after selecting a "candidate" entry.

    Like most of the remedies described on this page, this one makes an immediate change to the boot order but does not guarantee that the problem will not recur. In most cases, rEFInd will remain the primary boot program until it's changed again by another OS update, but all bets are off when that happens.

    @@ -424,9 +427,9 @@
  • Locate Command Prompt in the Start menu, right-click it, and select Run as Administrator. This action opens a Command Prompt window with administrative privileges.
  • -
  • Type bcdedit /set {bootmgr} path \EFI\refind\refind_x64.efi to set rEFInd as the default EFI boot program. Note that {bootmgr} is entered as such; that's not a notation for a variable. Also, change refind_x64.efi to refind_ia32.efi on systems with 32-bit EFIs. Such computers are rare, and most of them are tablets. Check your Windows bit depth to determine which binary you should use. If you use Shim or PreLoader to boot with Secure Boot active, you should change the name of the binary appropriately.
  • +
  • Type bcdedit /set "{bootmgr}" path \EFI\refind\refind_x64.efi to set rEFInd as the default EFI boot program. Note that "{bootmgr}" is entered as such; that's not a notation for a variable. Also, change refind_x64.efi to refind_ia32.efi on systems with 32-bit EFIs. Such computers are rare, and most of them are tablets. Check your Windows bit depth to determine which binary you should use. If you use Shim or PreLoader to boot with Secure Boot active, you should change the name of the binary appropriately.
  • -
  • If you like, type bcdedit /set {bootmgr} description "rEFInd description" to set a description (change rEFInd description as you see fit).
  • +
  • If you like, type bcdedit /set "{bootmgr}" description "rEFInd description" to set a description (change rEFInd description as you see fit).
  • @@ -470,7 +473,7 @@

    Using an EFI Shell to Adjust Your Boot Priority

    -

    Version 2 of the EFI shell provides a command, bcfg, which can adjust the EFI boot order. Unfortunately, this tool is not present in version 1 of the EFI shell, and version 2 is reliable only with EFI version 2.3 and later. To date (early 2016), all Intel-based Macs use EFI 1.1, and many PCs sold prior to Windows 8's release use UEFI (EFI 2.x) versions prior to 2.3. Thus, this approach may not work for you.

    +

    Version 2 of the EFI shell provides a command, bcfg, which can adjust the EFI boot order. Unfortunately, this tool is not present in version 1 of the EFI shell, and version 2 is reliable only with EFI version 2.3 and later. To date (mid-2017), all Intel-based Macs use EFI 1.1, and many PCs sold prior to Windows 8's release use UEFI (EFI 2.x) versions prior to 2.3. Thus, this approach may not work for you.

    Even if your computer works with a version 2 shell, it may not have one built in. In fact, most EFIs I've seen lack a built-in shell. If a shell is available, it should appear on the EFI's built-in boot manager, as described earlier, in Evading the Guards: Performing a One-Time Boot to Your Desired OS. If a shell is not built into your firmware, you can add one; here are a few links that may be helpful:

    @@ -547,6 +550,8 @@
  • Return the computer for a refund. If none of the preceding steps works, chances are your firmware is just plain defective. Note that by "defective" I mean "defective by design," not a sample defect, so you should not exchange the computer for another of the same model. (Indeed, even another model of the same brand may suffer from the same problem.) Your best bet in this case is to return the product to the store for a refund and write to the manufacturer about the problem. Manufacturers will not fix problems that they don't know exist, so informing them of the problem is important. Unfortunately, many people learn of such problems only after having owned a computer for months, so a return is not always practical....
  • +
  • Use the fallback.efi program. This approach is described shortly, in Managing Boot Coups with fallback.efi/fbx86.efi.
  • +
  • Use a fallback filename. You can use mvrefind in Linux to rename rEFInd to use either of two fallback filenames: @@ -214,27 +222,35 @@

    Identifying Your Windows Boot Mode

    - + + +

    Note that there are other ways to launch the System Information tool, so feel free to use one of them if you prefer it. Unfortunately, although Windows 7 provides the System Information utility, that version of the tool does not provide the boot mode information, so if you're using Windows 7, you must use another method to determine your boot mode.

    -

    The most reliable way I know of to identify your boot mode is to examine your partitions. Microsoft has tied use of the GUID Partition Table (GPT) to EFI booting. If you've booted from a GPT disk, then you must be using EFI, and if you've booted from a Master Boot Record (MBR) disk, you must have booted in BIOS mode. Therefore, you can check your partition table type as a proxy for your boot mode. To do this in Windows 7, follow these steps:

    +

    Using Your Partition Table Type

    + +

    If you can't use System Information to determine your boot mode, you can examine your partitions to identify your boot mode. Microsoft has tied use of the GUID Partition Table (GPT) to EFI booting. If you've booted from a GPT disk, then you must be using EFI, and if you've booted from a Master Boot Record (MBR) disk, you have almost certainly booted in BIOS mode. (I've heard of some exceptions to this rule, but they're exceedingly rare.) Therefore, you can check your partition table type as a proxy for your boot mode. To do this in Windows 7, follow these steps:

      @@ -258,9 +274,11 @@

      An important caveat with this method is that you must examine your boot disk. It's possible to use GPT on a data disk even on a BIOS-based computer, or to use an MBR data disk even on an EFI-based computer. Thus, if you examine the wrong disk, you can be led to an incorrect conclusion about your computer's boot mode.

      +

      Another caveat relates to the use of a hybrid MBR, which is a variant on a GPT disk that's most often used on Macs to permit booting Windows in BIOS mode and OS X in EFI mode. Most Windows tools will identify a hybrid MBR disk as an MBR disk, but most non-Windows tools will identify it as a GPT disk. Of course, as hybrid MBRs are generally used to enable dual-booting Windows and OS X, and as OS X boots in EFI mode, you should be able to install rEFInd from OS X to help manage such a dual-boot configuration.

      +
      -

      copyright © 2012–2016 by Roderick W. Smith

      +

      copyright © 2012–2017 by Roderick W. Smith

      This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

      diff -Nru refind-0.10.4/docs/refind/configfile.html refind-0.11.2/docs/refind/configfile.html --- refind-0.10.4/docs/refind/configfile.html 2016-10-09 17:16:35.000000000 +0000 +++ refind-0.11.2/docs/refind/configfile.html 2017-10-22 20:14:05.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

      Originally written: 3/14/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

      +10/22/2017, referencing rEFInd 0.11.2

      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!

      @@ -158,15 +158,29 @@

      Hiding and Displaying EFI Boot Loaders

      +

      A common complaint among rEFInd users is that rEFInd displays too many boot options. This problem is getting worse as OS vendors deliver more and more tools in the form of EFI programs installed on the ESP. It's difficult for me to keep up with this flood, and what one person considers a necessary program another may consider pointless clutter, making it hard to set useful defaults. Fortunately, rEFInd provides several ways to hide OSes—or to make them appear, if they don't by default. Methods to do this include:

      + +
        + + + +
      • Hiding entries dynamically—rEFInd 0.11.0 introduced a dynamic tag hiding feature. To use it, highlight a tag and hit the Delete (on PCs) or minus (-) key. (The Delete key on Macs is the Backspace key on PCs, and will not work for this; however, some Mac keyboards have a key marked Del that will do the job.) rEFInd will ask for confirmation. If you give it, the OS or external tool tag will disappear, and should remain hidden indefinitely. (Note that you cannot hide built-in tools, such as the About/Info display and the reboot-to-firmware option, in this way.) rEFInd stores the list of EFI OS tags so hidden in NVRAM using the HiddenTags variable, BIOS/CSM/legacy OS tags as HiddenLegacy, and tool tags as HiddenTools. If you want to recover a tag you've hidden, you can do so by using the hidden tag maintenance function, which appears on the second row of the rEFInd menu as a recycling symbol. You can disable both the ability to hide tags and to recover them by uncommenting the scanfor item in refind.conf and ensuring that hidden_tags is not among the options. (Even if you disable this feature, rEFInd continues to honor tags it finds in NVRAM.)
      • + -

        Before delving into the configuration file, you should be aware of what you can do by renaming files. By default, rEFInd scans all the filesystems it can read for boot loaders. It scans most of the subdirectories of the EFI directory on every filesystem it can access for files with names that end in .efi. (rEFInd gives special treatment to the tools subdirectory, where it looks for system tools rather than boot loaders.)

        +
      • Move, deleting, or renaming files—By default, rEFInd scans all the filesystems it can read for boot loaders. It scans most of the subdirectories of the EFI directory on every filesystem it can access for files with names that end in .efi. (rEFInd gives special treatment to the tools subdirectory, where it looks for system tools rather than boot loaders.) Thus, you can delete EFI program files, move them out of the directory tree that rEFInd scans, or rename them so that they don't have .efi extensions. Note that rEFInd does not scan its own directory or the EFI/tools directory, so those can be good places to stash seldom-used EFI binaries.
      • + +
      • dont_scan_volumes—This token in refind.conf specifies volumes that rEFInd will not scan. For EFI boot loaders, you can identify a volume by its filesystem label, partition name, or partition unique GUID value. On Macs, you can identify BIOS/CSM/legacy-mode OSes to hide by specifying any unique subset of the OS tag description shown in the rEFInd main menu. In either case, this token takes a comma-delimited list, as in dont_scan_volumes ESP7,BadVolume to blacklist the ESP7 and BadVolume partitions. This token cannot be used to hide BIOS/CSM/legacy-mode loaders on UEFI-based PCs.
      • -

        If you're like me, you may sometimes want to hide a boot loader from rEFInd's menu for a brief period—say, because you're testing a variety of configurations but you don't want them all to clutter the menu at once. You might also want to hide a boot loader if you want to override its default settings using a custom entry in refind.conf and you don't want an automatic search to duplicate that entry. You can easily hide a boot loader by removing or changing its .efi filename extension—for instance, changing grub.efi to grub.

        +
      • dont_scan_dirs—This token provides finer-grained control than the preceding one; you identify directories with this option. For instance, you might specify dont_scan_dirs EFI/ignore,BigDisk:/EFI/OldOS to ignore the EFI/ignore directory on all volumes and the EFI/OldOS directory on the BigDisk volume. This token cannot be used to hide BIOS/CSM/legacy-mode loaders.
      • -

        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.

        +
      • dont_scan_files—You can hide individual files with this token. Files can be specified alone, with a leading directory path, or with a leading directory path and volume name or GUID. For instance, dont_scan_files badloader.efi,EFI/ignoreme/boring.efi,MyDisk:/EFI/someos/grubx64.efi causes badloader.efi to be ignored in any location, EFI/ignoreme/boring.efi to be ignored on any disk, and EFI/someos/grubx64.efi to be ignored only on MyDisk. As with the previous items, you can identify a disk by filesystem label, partition name, or partition unique GUID.
      • -

        You can also use the dont_scan_volumes, dont_scan_dirs, and dont_scan_files tokens in refind.conf to hide entire volumes, directories, and individual files, respectively. Note that dont_scan_volumes works with both EFI and legacy scans, whereas the other two options make sense for hiding only EFI-mode boot loaders.

        +
      • also_scan_dirs—This token does the opposite of the preceding ones: It adds a directory to the scan list, so that rEFInd can locate boot loaders stored in unusual locations. This token takes a directory path, and optionally a name (filesystem or partition), but cannot currently take a GUID value as a volume identifier.
      • + +
      • scanfor—This token identifies the types of OSes for which rEFInd scans, and the types of devices on which it scans. On Macs, BIOS/CSM/legacy-mode scans are enabled by default; but you may want to disable this support by uncommenting the scanfor line and ensuring the hdbios, biosexternal, and cd are not present. These options are disabled by default on UEFI-based PCs, so if you want to boot BIOS-mode OSes, you must uncomment scanfor and add an appropriate option.
      • + +

      Setting OS Icons

      @@ -196,7 +210,7 @@

      In addition to the main OS tag icon, you can set the badge icon for a volume by creating a file called .VolumeBadge.icns or .VolumeBadge.png in the root directory of a partition. 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 add the badges option to hideui in refind.conf. Alternatively, or to hide just certain types of badges, you can replace the four badge icons in the rEFInd icons subdirectory (vol_external.png, vol_internal.png, vol_optical.png, and vol_net.png) with a completely transparent badge. The transparent.png file in the rEFInd icons directory may be used for this purpose.

      -

      The default icon sizes are 128x128 pixels for OS icons, 48x48 pixels for the second-row tools, and 32x32 pixels for badges. You can change the sizes of the big OS icons and the small tool icons with the big_icon_size and small_icon_size tokens in refind.conf, as noted in Table 1. The size of the disk-type badges is 1/4 the size of OS icons.

      +

      The default icon sizes are 128x128 pixels for OS icons, 48x48 pixels for the second-row tools, and 32x32 pixels for badges. (These figures are all doubled on displays wider than 1920 pixels.) You can change the sizes of the big OS icons and the small tool icons with the big_icon_size and small_icon_size tokens in refind.conf, as noted in Table 1. The size of the disk-type badges is 1/4 the size of OS icons.

      Adjusting the Global Configuration

      @@ -267,12 +281,12 @@ big_icon_size numeric value (at least 32) - Sets the size of big icons (those used for OSes on the first row). All icons are square, so only one value is specified. If icon files don't contain images of the specified size, the available images are scaled to this size. The disk-type badge size is set indirectly by this token; badges are 1/4 the size of big icons. The default value is 128. + Sets the size of big icons (those used for OSes on the first row). All icons are square, so only one value is specified. If icon files don't contain images of the specified size, the available images are scaled to this size. The disk-type badge size is set indirectly by this token; badges are 1/4 the size of big icons. The default value is 128 on most systems, or 256 when the screen is wider than 1920 pixels. small_icon_size numeric value (at least 32) - Sets the size of small icons (those used for tools on the second row). All icons are square, so only one value is specified. If icon files don't contain images of the specified size, the available images are scaled to this size. The default value is 128. + Sets the size of small icons (those used for tools on the second row). All icons are square, so only one value is specified. If icon files don't contain images of the specified size, the available images are scaled to this size. The default value is 48 on most systems, or 96 when the screen is wider than 1920 pixels. selection_big @@ -286,8 +300,8 @@ showtools - shell, memtest, gdisk, gptsync, apple_recovery, csr_rotate, mok_tool, fwupdate, netboot, about, exit, shutdown, reboot, and firmware - Specifies which tool tags to display on the second row. shell launches an EFI shell, memtest (or memtest86) launches the
      Memtest86 program, gdisk launches the partitioning tool of the same name, gptsync launches a tool that creates a hybrid MBR, apple_recovery boots the OS X Recovery HD, csr_rotate rotates through System Integrity Protection (SIP) values specified by csr_values, windows_recovery boots a Windows recovery tool, mok_tool launches a tool to manage Machine Owner Keys (MOKs) on systems with Secure Boot active, fwupdate launches a firmware-update tool, netboot launches the network boot tool (iPXE), about displays information about rEFInd, exit terminates rEFInd, shutdown shuts down the computer (or reboots it, on some UEFI PCs), reboot reboots the computer, and firmware reboots the computer into the computer's own setup utility. The tags appear in the order in which you specify them. The default is shell, memtest, gdisk, apple_recovery, mok_tool, about, shutdown, reboot, firmware. Note that the shell, memtest, apple_recovery, and mok_tool options all require the presence of programs not included with rEFInd. The gptsync option requires use of a like-named program which, although it ships with rEFInd 0.6.9 and later, is not installed by default except under OS X. See the "Installing Additional Components" section of the Installing rEFInd page for pointers to the shell, Memtest86, and gptsync programs. The apple_recovery option will appear only if you've got an Apple Recovery HD partition (which has a boot loader called com.apple.recovery.boot/boot.efi). The firmware option works only on computers that support this option; on other computers, the option is quietly ignored. See the Secure Boot page for information on Secure Boot and MOK management. + shell, memtest, gdisk, gptsync, apple_recovery, csr_rotate, mok_tool, fwupdate, netboot, about, hidden_tags, exit, shutdown, reboot, and firmware + Specifies which tool tags to display on the second row. shell launches an EFI shell, memtest (or memtest86) launches the Memtest86 program, gdisk launches the partitioning tool of the same name, gptsync launches a tool that creates a hybrid MBR, apple_recovery boots the OS X Recovery HD, csr_rotate rotates through System Integrity Protection (SIP) values specified by csr_values, windows_recovery boots a Windows recovery tool, mok_tool launches a tool to manage Machine Owner Keys (MOKs) on systems with Secure Boot active, fwupdate launches a firmware-update tool, netboot launches the network boot tool (iPXE), about displays information about rEFInd, hidden_tags enables you to recover tags you've hidden exit terminates rEFInd, shutdown shuts down the computer (or reboots it, on some UEFI PCs), reboot reboots the computer, and firmware reboots the computer into the computer's own setup utility. The tags appear in the order in which you specify them. The default is shell, memtest, gdisk, apple_recovery, mok_tool, about, shutdown, reboot, firmware. Note that the shell, memtest, apple_recovery, and mok_tool options all require the presence of programs not included with rEFInd. The gptsync option requires use of a like-named program which, although it ships with rEFInd 0.6.9 and later, is not installed by default except under OS X. See the "Installing Additional Components" section of the Installing rEFInd page for pointers to the shell, Memtest86, and gptsync programs. The apple_recovery option will appear only if you've got an Apple Recovery HD partition (which has a boot loader called com.apple.recovery.boot/boot.efi). The firmware option works only on computers that support this option; on other computers, the option is quietly ignored. See the Secure Boot page for information on Secure Boot and MOK management. font @@ -312,7 +326,22 @@ enable_touch none or one of true, on, 1, false, off, or 0 - Enables support for touch screens (as on tablets). Note that not all tablets provide the necessary support. If this feature is enabled and the tablet supports it, touching an OS or tool should launch it or enter a submenu. In a submenu, it is currently not possible to select a specific item; any touch will launch the default submenu option. + Enables support for touch screens (as on tablets). Note that not all tablets provide the necessary support. If this feature is enabled and the tablet supports it, touching an OS or tool should launch it or enter a submenu. In a submenu, it is currently not possible to select a specific item; any touch will launch the default submenu option. This option is incompatible with enable_mouse. If both are specified, the one appearing later in refind.conf takes precedence. The default is off. + + + enable_mouse + none or one of true, on, 1, false, off, or 0 + Enables support for mice (and related pointing devices). Note that not all tablets provide the necessary support. If this feature is enabled and the computer supports it, clicking an OS or tool should launch it or enter a submenu. In a submenu, it is currently not possible to select a specific item; any click will launch the default submenu option. This option is incompatible with enable_touch. If both are specified, the one appearing later in refind.conf takes precedence. The default is off. + + + mouse_size + numeric value + Sets the size of the mouse pointer, in pixels squared. The default is 16. + + + mouse_speed + numeric value + Sets the speed of the mouse pointer, with higher numbers meaning faster tracking. The default is 1. use_graphics_for @@ -347,17 +376,22 @@ dont_scan_volumes or don't_scan_volumes filesystem or partition label(s) - Adds the specified volume or volumes to a volume "blacklist"—these filesystems are not scanned for EFI boot loaders. This may be useful to keep unwanted EFI boot entries, such as for a Macintosh recovery partition, from appearing on the main list of boot loaders. The default value is LRS_ESP, to keep the Lenovo Windows recovery volume from appearing. (This volume should get its own tools icon instead—see the showtools token.) You can use dont_scan_volumes to hide disks or partitions from legacy-mode scans, too. In this case, you can enter any part of the description that appears beneath the icons to hide entries that include the string you specify. + Adds the specified volume or volumes to a volume "blacklist"—these filesystems are not scanned for EFI boot loaders. This may be useful to keep unwanted EFI boot entries, such as for an OS recovery partition, from appearing on the main list of boot loaders. You can identify a volume by its filesystem name, its GPT volume name, or by its GPT unique GUID value. The default value is LRS_ESP, to keep the Lenovo Windows recovery volume from appearing. (This volume should get its own tools icon instead—see the showtools token.) You can use dont_scan_volumes to hide disks or partitions from legacy-mode scans, too. In this case, you can enter any part of the description that appears beneath the icons to hide entries that include the string you specify. dont_scan_dirs or don't_scan_dirs directory path(s) - Adds the specified directory or directories to a directory "blacklist"—these directories are not 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, EFI/BOOT prevents scanning the EFI/BOOT directory on all volumes, whereas ESP:EFI/BOOT blocks scans of EFI/BOOT on the volume called ESP but not on other volumes. You can use a filesystem number, as in fs0, in place of a volume name. (The use of filesystem numbers is deprecated.) 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 EFI. This option takes precedence over also_scan_dirs; if a directory appears in both lists, it will not be scanned. To add directories to the default list rather than replace the list, specify + as the first option, as in dont_scan_dirs + EFI/dontscan. The default for this token is EFI/tools, EFI/tools/memtest86, EFI/tools/memtest, EFI/memtest86, EFI/memtest, com.apple.recovery.boot. + Adds the specified directory or directories to a directory "blacklist"—these directories are not 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, EFI/BOOT prevents scanning the EFI/BOOT directory on all volumes, whereas ESP:EFI/BOOT blocks scans of EFI/BOOT on the volume called ESP but not on other volumes. You can use a filesystem unique GUID, as in 2C17D5ED-850D-4F76-BA31-47A561740082, 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 EFI. This option takes precedence over also_scan_dirs; if a directory appears in both lists, it will not be scanned. To add directories to the default list rather than replace the list, specify + as the first option, as in dont_scan_dirs + EFI/dontscan. The default for this token is EFI/tools, EFI/tools/memtest86, EFI/tools/memtest, EFI/memtest86, EFI/memtest, com.apple.recovery.boot. dont_scan_files or don't_scan_files filename(s) - Adds the specified filename or filenames to a filename "blacklist"—these files are not included as boot loader options even if they're found on the disk. This is useful to exclude support programs (such as shim.efi and MokManager.efi) and drivers from your OS list. The default value is shim.efi, shim-fedora.efi, shimx64.efi, PreLoader.efi, TextMode.efi, ebounce.efi, GraphicsConsole.efi, MokManager.efi, HashTool.efi, HashTool-signed.efi. You can add a pathname and even a volume specification, as in ESP:/EFI/BOOT/backup.efi, /boot/vmlinuz-bad, to block the boot loaders only in those specified locations. To add files to the default list rather than replace the list, specify + as the first option, as in dont_scan_files + badloader.efi. + Adds the specified filename or filenames to a filename "blacklist" for OS loaders—these files are not included as boot loader options even if they're found on the disk. This is useful to exclude support programs (such as shim.efi and MokManager.efi) and drivers from your OS list. The default value is shim.efi, shim-fedora.efi, shimx64.efi, PreLoader.efi, TextMode.efi, ebounce.efi, GraphicsConsole.efi, MokManager.efi, HashTool.efi, HashTool-signed.efi, fb{arch}.efi (where {arch} is the architecture code, such as x64). You can add a pathname and even a volume specification (filesystem name, partition name, or partition unique GUID), as in ESP:/EFI/BOOT/backup.efi, /boot/vmlinuz-bad, to block the boot loaders only in those specified locations. To add files to the default list rather than replace the list, specify + as the first option, as in dont_scan_files + badloader.efi. + + + dont_scan_tools or don't_scan_tools + filename(s) + Adds the specified filename or filenames to a filename "blacklist" for tools—these files are not included as tools (second-line options) even if they're found on the disk and are specified to be included via showtools. This is useful to trim an overabundance of tools. For instance, if you install multiple Linux distributions, you may end up with multiple MokManager entries, but you'll need just one. You can add a pathname and even a volume specification (filesystem name, partition name, or partition unique GUID), as in ESP:/EFI/tools/shellx64.efi, EFI/ubuntu/mmx64.efi, to block the tools only in those specified locations. The default value is an empty list (nothing is excluded). windows_recovery_files @@ -375,14 +409,26 @@ When uncommented or set to true, on, or 1, causes rEFInd to "fold" all Linux kernels in a given directory into a single main-menu icon. Selecting that icon launches the most recent kernel. To launch an older kernel, you must press F2 or Insert; older kernels appear on the resulting submenu display. (You can type, as root, touch /boot/vmlinuz-{whatever}, to make /boot/vmlinuz-{whatever} your default kernel in a directory.) If you prefer to see all your kernels in the main menu, set this option to false, off, or 0. Note that this option is new with version 0.9.0, which changes the default behavior; earlier versions of rEFInd behaved as if fold_linux_kernels false was set. + extra_kernel_version_strings + comma-delimited list of strings + For the benefit of Linux distributions, such as Arch, that lack version numbers in their kernel filenames but that can provide multiple kernels, you can specify strings that can treated like version numbers. For instance, for Arch you might set this to linux-lts,linux; thereafter, the vmlinuz-linux-lts kernel will match to an initrd file containing the string linux-lts and vmlinuz-linux will match an initrd file with a filename that includes linux, but not linux-lts. Note that, if one specified string is a subset of the other (as in this example), the longer substring must appear first in the list. Also, if a filename includes both a specified string and one or more digits, the match covers both; for instance, vmlinuz-linux-4.8 would match an initrd file with a name that includes linux-4.8. The default is to do no extra matching. + + max_tags numeric (integer) value Limits the number of tags that rEFInd will display at one time. If rEFInd discovers more loaders than this value, they're shown in a scrolling list. The default value is 0, which imposes no limit. default_selection - a substring of a boot loader's title, or a numeric position; optionally followed by two times in HH:MM format - Sets the default boot OS based on the loader's title, which appears in the main menu beneath the icons when you select the loader. You can enter any substring of the title as the default_selection, so long as it's two or more characters in length. It's best to use a unique substring, since rEFInd stops searching when it finds the first match. Because rEFInd sorts entries within a directory in descending order by file modification time, if you specify a directory (or volume name, for loaders in a partition's root directory) as the default_selection, the newest 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. If you specify a comma-delimited list of names in quotation marks, rEFInd will search on these in turn until it finds a match. For instance, default_selection "alpha,beta" will launch alpha if it's available, and beta if alpha is not available but beta is. If the first item in such a list is a plus sign (+), that refers to the item that rEFInd launched the last time it ran. You may optionally follow the match string by two times, in 24-hour format, in which case the entry applies only between those two times. For instance, default_selection Safety 1:30 2:30 boots the entry called Safety by default between the hours of 1:30 and 2:30. These times are specified in whatever format the motherboard clock uses (local time or UTC). If the first value is larger than the second, as in 23:00 1:00, it is interpreted as crossing midnight—11:00 PM to 1:00 AM in this example. The last default_selection setting takes precedence over preceding ones if the time value matches. Thus, you can set a main default_selection without a time specification and then set one or more others to override the main setting at specific times. If you do not specify a default_selection, rEFInd attempts to boot the previously-booted entry, or the first entry if there's no record of that or if the previously-booted entry can't be found. + a substring of a boot loader's title, +, or a numeric position; optionally followed by two times in HH:MM format + 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. This token takes one or three variables. The first variable is a set of one or more identifiers. If you specify more than one or if the identifier contains a space, it must be in quotation marks. If more than one identifier is present, they must be specified as a comma-separated list, all within a single set of quotation marks. For instance, default_selection "alpha,beta" will launch alpha if it's available, and beta if alpha is not available but beta is. Each identifier can be any one of three things: +
        +
      • The symbol +, which refers to the previously-launched boot entry. rEFInd stores (in NVRAM) the name of a boot entry before launching it, and effectively substitutes that stored string for the + in the default_selection line the next time rEFInd launches, then matches it as a string, as described next....
      • +
      • Any string, which is matched against boot descriptions. Note that rEFInd matches substrings, so you don't need to specify the complete description string, just a unique substring. Thus, default_selection vmlinuz matches vmlinuz, boot\vmlinuz-4.8.0-22-generic, or any other string that includes vmlinuz. rEFInd stops searching when it finds the first match. Because rEFInd sorts entries within a directory in descending order by file modification time, if you specify a directory (or volume name, for loaders in a partition's root directory) as the default_selection, the newest loader in that directory will be the default. As a special case, one-character strings are matched against the first character of the description, except for digits.
      • +
      • A digit (1 to 9), in which case the boot loader at that position in the boot list is launched. For instance, default_selection 2 makes the second boot entry the default.
      • +
      + + You may optionally follow the match string by two times, in 24-hour format, in which case the entry applies only between those two times. For instance, default_selection Safety 1:30 2:30 boots the entry called Safety by default between the hours of 1:30 and 2:30. These times are specified in whatever format the motherboard clock uses (local time or UTC). If the first value is larger than the second, as in 23:00 1:00, it is interpreted as crossing midnight—11:00 PM to 1:00 AM in this example. The last default_selection setting takes precedence over preceding ones if the time value matches. Thus, you can set a main default_selection without a time specification and then set one or more others to override the main setting at specific times. If you do not specify a default_selection, rEFInd attempts to boot the previously-booted entry, or the first entry if there's no record of that or if the previously-booted entry can't be found. enable_and_lock_vmx @@ -654,7 +700,7 @@
      -

      copyright © 2012–2016 by Roderick W. Smith

      +

      copyright © 2012–2017 by Roderick W. Smith

      This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

      diff -Nru refind-0.10.4/docs/refind/drivers.html refind-0.11.2/docs/refind/drivers.html --- refind-0.10.4/docs/refind/drivers.html 2016-10-09 22:44:01.000000000 +0000 +++ refind-0.11.2/docs/refind/drivers.html 2017-10-22 20:28:39.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

      Originally written: 4/19/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

      +10/22/2017, referencing rEFInd 0.11.2

      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!

      @@ -163,12 +163,14 @@
    1. You can load a filesystem driver to gain access to files on a filesystem other than FAT (or HFS+ on Macs or ISO-9660 on some systems). This is most likely to be useful on a Linux installation, since a filesystem driver can enable you to store a Linux kernel with EFI stub loader or for use by ELILO on a Linux-native filesystem if your EFI System Partition (ESP) is getting crowded.
    2. -
    3. You can load a driver for a plug-in disk controller to give the EFI access to its disks. Note that this is not required if you place your boot loader (and perhaps your OS kernel) on another disk, or if the plug-in disk controller includes EFI-capable firmware. It could be handy, perhaps in conjunction with a filesystem driver, to enable the EFI to read a boot loader or kernel from a disk on a plug-in controller, though.
    4. +
    5. You can load a driver for a plug-in disk controller to give the EFI access to its disks. Note that this is not required if you place your boot loader (and perhaps your OS kernel) on another disk, or if the plug-in disk controller includes EFI-capable firmware. It could be handy, perhaps in conjunction with a filesystem driver, to enable the EFI to read a boot loader or kernel from a disk on a plug-in controller, though. I've received one report of the NVMe driver from Clover being useful to boot from an aftermarket NVMe disk on a Mac, for instance.
    6. You can load a driver for a plug-in network card to enable the computer to boot from the network, or to access the network without booting an OS. Note that rEFInd does not currently support network boots itself, though.
    7. You can load a video card driver to set an appropriate video mode or to support a plug-in card that lacks EFI support in ts own firmware.
    8. +
    9. You can load a mouse or touchscreen driver to enable the mouse or touchscreen to work even if your firmware lacks this support. (Note that you must also explicitly activate rEFInd's mouse or touch support in refind.conf for the driver to be useful.) Note that I've not tested this myself or heard of it working, but in theory it should work, provided you find a compatible driver.
    10. +

      Note that most of these uses are theoretical, at least to me; I don't know of any specific examples of EFI drivers (available as separate files) for disk controller hardware, network cards, or video cards. Such drivers are often embedded in the firmware of the devices themselves, and should be loaded automatically by the EFI. Chances are good that a few such drivers are available, unknown to me, and more may become available in the future. If you happen to have a device and need support for it under EFI, searching for drivers is certainly worth doing.

      @@ -346,11 +348,13 @@
    11. Pete Batard's efifs drivers—This project is an EFI driver wrapper around GRUB 2's filesystem drivers. Once compiled, the result is that GRUB 2's drivers become standalone EFI filesystem drivers, loadable independently or by rEFInd. (rEFInd version 0.8.3 or later is required.) At present (driver version 1.0; July 2016), several drivers, including NTFS, exFAT, ext2fs, ReiserFS, Btrfs, JFS, and XFS, are usable. The last time I tested them (version 0.7), some drivers were slow, and they hung on some computers, such as one of my Macs. They may have improved since then, and are likely to improve more in the future. Note that the ext2fs driver from this set works with ext3fs and ext4fs, too. In addition to the main link, you can check the github repository for the source code.
    12. +
    13. The LKL driver project—I have yet to look closely at this project, but I think it's a porting of the Linux kernel's filesystem drivers to EFI. The developer stated on the EFI developers' mailing list that they aren't yet stable, as of November 2016.
    14. +
    15. rEFIt's ext2fs and ReiserFS drivers—You can gain read-only access to ext2fs, ext3fs, and ReiserFS volumes with these drivers, originally written by Christoph Pfisterer. You can use the binaries in the refit-bin-0.14/efi/tools/drivers directory of the binary package directly on a Mac. On a UEFI-based PC, though, you'll need to break the Mac-style "fat" binary into its 32- and 64-bit components. You can use my thin program for this job. As a practical matter, there's no advantage to using these drivers over rEFInd's drivers, since the latter are updated versions of the former.
    16. Clover EFI's ISO-9660, ext2fs, ext4fs, and HFS+ drivers—This project is an offshoot of TianoCore, the main UEFI project. It's primarily a Hackintosh boot loader, but it includes drivers for ISO-9660, ext2fs, ext4fs, and HFS+; however, building them requires a fair amount of expertise. These drivers are closely related to rEFInd's own drivers. Thus, as with the rEFIt drivers, there's likely to be no advantage to using the Clover drivers over the rEFInd drivers.
    17. -
    18. Clover's EFI Tools package—This osx86.net thread includes links to a package called EFI_Tools_Clover_v2_r1888_EN.zip, which holds an OS X application (a directory with a .app extension, as seen from other platforms) with a number of drivers in the Contents/Resources/EFI/drivers64 directory (and an equivalent for 32-bit binaries). Some of these, such as keyboard drivers, are unlikely to be useful unless your system is badly broken as delivered. Three that caught my eye, however, are VBoxExt2-64.efi, VBoxIso9600-64.efi, and NTFS-64.efi. The first two of those are presumably variants on rEFInd's drivers, but the NTFS driver is not. I don't know this driver's provenance, so I'm reluctant to recommend its use, but it bears mentioning.
    19. +
    20. Clover's non-filesystem drivers—In addition to its filesystem drivers, Clover includes a number of hardware drivers, such as one for NVMe devices (nvmexpressdxe-64.efi) and two mouse drivers (ps2mousedxe-64.efi and usbmousedxe-64.efi, for PS/2 and USB mice, respectively). I haven't tested these drivers, but I've received a report that the NVMe driver, at least, is useful to enable booting OSes installed on NVMe devices. The easiest way to obtain these drivers is likely to be to download the .iso file, mount it, and copy the drivers from the efi/clover/drivers* directories (there are several, with varying purposes). I recommend caution when testing them, though; using an inappropriate driver could cause a system hang.
    21. VirtualBox's HFS+ and ISO-9660 drivers—These drivers are available in source code form, and come with VirtualBox binaries. I've not attempted to compile them myself, but I've seen a report that suggests they may include assumptions that require use of MinGW, a GCC-based compiler for Windows (and cross-compiler to build Windows executables under Linux). I don't know of a source for binaries suitable for use on EFI-based computers; if you want to use them, you'll need to figure out how to compile them yourself. As noted earlier, rEFInd's drivers are closely related to these.
    22. @@ -358,9 +362,11 @@
    23. Paragon's UFSD—According to this blog post, Paragon Software has ported its Universal File System Drivers (UFSD) to EFI, providing "transparent access to NTFS, HFS+, ExFAT, and ExtFS" (sic). The entry doesn't provide any download links, and it's unclear if the product is (or will be) available for free or on a pay basis. I haven't tried these drivers, so I can't comment on their quality.
    24. +
    25. Apple's APFS—Apple provides an EFI driver for its Apple Filesystem (APFS), which is an optional feature of macOS 10.12 ("Sierra") and a mandatory feature of macOS 10.13 ("High Sierra") when using flash storage devices such as SSDs. When updating to macOS 10.13, your firmware should receive an update that includes this driver, so you shouldn't need to do anything to use APFS (with one caveat, described shortly). Apple also provides the driver as an EFI binary file, stored at /usr/standalone/i386/apfs.efi in the installed OS. You can load this driver from rEFInd, but doing so is likely to be pointless—on Macs, the driver should be built into the firmware, and on non-Macs, APFS is unlikely to hold files that rEFInd could use. On the off chance that a firmware update failed, though, copying this file to the rEFInd drivers subdirectory may enable you to boot macOS. Note that APFS includes built-in LVM-like features, similar to Btrfs. Under EFI, APFS volumes are identified by directories with UUIDs as filenames. This fact means that rEFInd 0.11.1 needed modifications to locate the macOS boot loader, since its location changed, as viewed from rEFInd. If you had used rEFInd 0.11.0 or earlier, update to macOS 10.13, and find that you can no longer boot macOS, try updating rEFInd to 0.11.1 or later.
    26. + -

      The rEFIt, Clover, and VirtualBox drivers are related, and all of them +

      The rEFIt, Clover filesystem, and VirtualBox drivers are related, and all of them have fed into rEFInd's drivers. Specific versions can have their own quirks, though. For instance, the Clover (and I suspect VirtualBox) drivers don't return volume labels, which causes rEFInd to display loaders on those @@ -399,7 +405,7 @@


      -

      copyright © 2012–2016 by Roderick W. Smith

      +

      copyright © 2012–2017 by Roderick W. Smith

      This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

      diff -Nru refind-0.10.4/docs/refind/features.html refind-0.11.2/docs/refind/features.html --- refind-0.10.4/docs/refind/features.html 2016-10-09 16:59:52.000000000 +0000 +++ refind-0.11.2/docs/refind/features.html 2017-10-22 20:11:34.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

      Originally written: 3/14/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

      +10/22/2017, referencing rEFInd 0.11.2

      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!

      @@ -190,6 +190,8 @@
    27. The ability to specify volumes and directories to not be scanned for boot loaders, even if they would ordinarily be scanned (as of version 0.6.0 for volumes and 0.4.2 for directories).
    28. +
    29. The ability to specify boot loader files to be ignored. This can be set either in the configuration file or dynamically as you're using rEFInd.
    30. +
    31. 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).
    32. A configurable delay before scanning for boot loaders, for systems on which there's a delay before disks become available (as of version 0.4.6).
    33. @@ -208,9 +210,11 @@
    34. The ability to handle some (but not all) touch-screen displays, as used on tablet computers.
    35. +
    36. On some (but not all) computers, the ability to handle mouse input to select the boot loader to run.
    37. +
    38. Additional OS icons (most of which are Linux distributions, at least so far). This can make it easier to find a specific distribution in the boot list if you've installed multiple Linux distributions.
    39. -
    40. Beginning with version 0.6.6, support for loading user-defined fonts, in the form of PNG files containing ASCII characters 32 through 126 plus a glyph to be used for values outside that range.
    41. +
    42. Support for loading user-defined fonts, in the form of PNG files containing ASCII characters 32 through 126 plus a glyph to be used for values outside that range.
    43. The ability to auto-detect Linux initial RAM disk files and to read Linux kernel options from a refind_linux.conf file. These features support (nearly) automatic handling of Linux kernels with embedded EFI stub loader support (a new feature with Linux 3.3.0).
    44. @@ -254,7 +258,7 @@
      -

      copyright © 2012–2016 by Roderick W. Smith

      +

      copyright © 2012–2017 by Roderick W. Smith

      This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

      diff -Nru refind-0.10.4/docs/refind/getting.html refind-0.11.2/docs/refind/getting.html --- refind-0.10.4/docs/refind/getting.html 2016-10-09 17:01:37.000000000 +0000 +++ refind-0.11.2/docs/refind/getting.html 2017-10-22 20:12:06.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

      Originally written: 3/14/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

      +10/22/2017, referencing rEFInd 0.11.2

      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!

      @@ -132,7 +132,7 @@
    45. Additional programs @@ -270,7 +276,7 @@
      -

      copyright © 2012–2016 by Roderick W. Smith

      +

      copyright © 2012–2017 by Roderick W. Smith

      This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

      diff -Nru refind-0.10.4/docs/refind/installing.html refind-0.11.2/docs/refind/installing.html --- refind-0.10.4/docs/refind/installing.html 2016-10-09 17:07:56.000000000 +0000 +++ refind-0.11.2/docs/refind/installing.html 2017-10-22 20:12:38.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

      Originally written: 3/14/2012; last Web page update: -9/10/2016, referencing rEFInd 0.10.4

      +10/22/2017, referencing rEFInd 0.11.2

      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!

      @@ -214,15 +214,15 @@

      I provide RPM and Debian package files for rEFInd; and starting with version 0.8.1, I'm maintaining an Ubuntu PPA for rEFInd. If you have a working RPM-based or Debian-based Linux installation that boots in EFI mode, using one of these files is likely to be the easiest way to install rEFInd: You need only download the file and issue an appropriate installation command. In some cases, double-clicking the package in your file manager will install it. If that doesn't work, a command like the following will install the RPM on an RPM-based system:

      -
      # rpm -Uvh refind-0.10.4-1.x86_64.rpm
      +
      # rpm -Uvh refind-0.11.2-1.x86_64.rpm

      On a Debian-based system, the equivalent command is:

      -
      # dpkg -i refind_0.10.4-1_amd64.deb
      +
      # dpkg -i refind_0.11.2-1_amd64.deb
      - + -

      Either command produces output similar to that described for using the refind-install script, so you can check it for error messages and other signs of trouble. The package file installs rEFInd and registers it with the EFI to be the default boot loader. The script that runs as part of the installation process tries to determine if you're using Secure Boot, and if so it will try to configure rEFInd to launch using shim; however, this won't work correctly on all systems. Ubuntu 12.10 users who are booting with Secure Boot active should be wary, since the resulting installation will probably try to use Ubuntu's version of shim, which won't work correctly with rEFInd. The shim program provided with more recent versions of Ubuntu should work correctly.

      +

      Either command produces output similar to that described for using the refind-install script, so you can check it for error messages and other signs of trouble. The package file installs rEFInd and registers it with the EFI to be the default boot loader. The script that runs as part of the installation process tries to determine if you're using Secure Boot, and if so it will try to configure rEFInd to launch using shim; however, this won't work correctly on all systems. Ubuntu 12.10 users who are booting with Secure Boot active should be wary, since the resulting installation will probably try to use Ubuntu's version of shim, which won't work correctly with rEFInd. The shim program provided with more recent versions of Ubuntu should work correctly. Also, since version 0.11.0, refind-install supports storing Secure Boot private keys in an encrypted form. If you set up rEFInd in this way, the RPM or Debian package will fail to install, since it assumes an unencrypted Secure Boot key.

      If you're using Ubuntu, you should be able to install the PPA as follows:

      @@ -457,8 +457,6 @@

      The EasyUEFI tool is a free (as in beer) GUI tool for managing EFI boot programs. I've only tried it once, and it seemed fairly intuitive and easy to use, but I don't have detailed instructions on how to use it. If you want to use EasyUEFI, you'll have to use it in place of bcdedit at the end of the following procedure.

      - -

      Attempt this method of installation only on a UEFI-based PC; this method will not work on Windows that's installed on a Mac in BIOS/CSM/legacy mode. To install rEFInd under Windows, you must first find a way to access the ESP, which Windows normally hides from view. One way to accomplish this goal, and to proceed forward once the ESP is accessible, is as follows:

        @@ -479,11 +477,9 @@
      1. Type rename refind.conf-sample refind.conf to rename rEFInd's configuration file.
      2. - - -
      3. Type bcdedit /set {bootmgr} path \EFI\refind\refind_x64.efi to set rEFInd as the default EFI boot program. Note that {bootmgr} is entered as such; that's not a notation for a variable. Also, change refind_x64.efi to refind_ia32.efi on systems with 32-bit EFIs. Such computers are rare, and most of them are tablets. Check your Windows bit depth to determine which binary you should use.
      4. +
      5. Type bcdedit /set "{bootmgr}" path \EFI\refind\refind_x64.efi to set rEFInd as the default EFI boot program. Note that "{bootmgr}" is entered as such, including both the quotes and braces ({}). Also, change refind_x64.efi to refind_ia32.efi on systems with 32-bit EFIs. Such computers are rare, and most of them are tablets. Check your Windows bit depth to determine which binary you should use.
      6. -
      7. If you like, type bcdedit /set {bootmgr} description "rEFInd description" to set a description (change rEFInd description as you see fit).
      8. +
      9. If you like, type bcdedit /set "{bootmgr}" description "rEFInd description" to set a description (change rEFInd description as you see fit).
      @@ -513,15 +509,13 @@ -

      Note that the IA32 shell included in rEFInd's CD-R image version is a version 1 shell, so you can't use it for this purpose. You can, however, copy rEFInd's files from the CD-R. You can even launch the version 1 shell included with rEFInd and then use that to launch a version 2 shell. The x86-64 shell on the CD-R is the alternate shell, which should work on any x86-64 computer. Once you've booted the shell, you can proceed as follows:

      +

      Once you've booted the shell, you can proceed as follows:

        @@ -1094,7 +1088,7 @@
        -

        copyright © 2012–2015 by Roderick W. Smith

        +

        copyright © 2012–2017 by Roderick W. Smith

        This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

        diff -Nru refind-0.10.4/docs/refind/linux.html refind-0.11.2/docs/refind/linux.html --- refind-0.10.4/docs/refind/linux.html 2016-10-09 22:45:56.000000000 +0000 +++ refind-0.11.2/docs/refind/linux.html 2017-10-22 20:28:50.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

        Originally written: 3/19/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

        +10/22/2017, referencing rEFInd 0.11.2

        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!

        @@ -126,7 +126,9 @@
        -

        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.

        +

        Windows and Mac OS X both provide relatively simple EFI boot loader programs. Launch them, and they'll boot their respective OSes. This makes rEFInd's job easy; it just locates the boot loader program files and runs them.

        + +

        Under Linux, by contrast, things can get complicated. As detailed on my Managing EFI Boot Loaders for Linux page, several different EFI boot loaders for Linux exist, and all of them require configuration. If you're lucky, your distribution will have set up a Linux boot loader in a sensible way, in which case rEFInd should detect it and it will work as easily as a Windows or Mac OS X boot loader. If you're not lucky, though, you may need to configure it further. rEFInd offers options to help out with this task. Naturally, rEFInd supports traditional Linux boot loaders. It works even better with the Linux EFI stub loader, so I provide instructions on starting with it. For those interested in manual configuration, I also provide detailed instructions on how the EFI stub support works and how to configure it.

        @@ -156,8 +158,6 @@ -

        Under Linux, by contrast, things can get complicated. As detailed on my Managing EFI Boot Loaders for Linux page, several different EFI boot loaders for Linux exist, and all of them require configuration. If you're lucky, your distribution will have set up a Linux boot loader in a sensible way, in which case rEFInd should detect it and it will work as easily as a Windows or Mac OS X boot loader. If you're not lucky, though, you may need to configure it further. rEFInd offers options to help out with this task. Naturally, rEFInd supports traditional Linux boot loaders. It works even better with the Linux EFI stub loader, so I provide instructions on starting with it. For those interested in manual configuration, I also provide detailed instructions on how the EFI stub support works and how to configure it.

        -

        Using a Traditional Linux Boot Loader

        @@ -172,7 +172,7 @@

        Using the EFI Stub Loader: Three Configuration Options

        -

        The EFI stub loader is basic and reliable, but it requires some setup to use it on some computers. It also requires that you run a kernel with the same bit width as your EFI. In most cases, this means running a 64-bit kernel, since 32-bit EFI-based computers are so rare. I describe three methods of using the EFI stub loader: an easiest method for those with compatible partition and filesystem layouts, a quick test configuration for those without such a layout, and a long-term setup for those without the ideal setup.

        +

        The EFI stub loader is basic and reliable, but it requires some setup to use it on some computers. It also requires that you run a kernel with the same bit width as your EFI. In most cases, this means running a 64-bit kernel, since 32-bit EFI-based computers are so rare. I describe three methods of using the EFI stub loader: an easiest method for those with compatible partition and filesystem layouts, a quick test configuration for those without such a layout, and a long-term setup for those without the ideal setup. In most cases, the first (easiest) method works fine, thanks to rEFInd's filesystem drivers and rEFInd features intended to help launch a kernel with minimal user configuration.

        For Those With Foresight or Luck: The Easiest Method

        @@ -210,7 +210,7 @@

        Preparing a Test Configuration

        -

        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 since version 17, Ubuntu since 12.10, and most 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:

        +

        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. (Most 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:

          @@ -243,7 +243,7 @@
        -

        You can continue to boot your computer with this type of configuration; however, the drawback is that you'll need to copy your kernel whenever it's updated. This can be a hassle. A better way is to configure you system so that the EFI, and therefore rEFInd, can read your Linux /boot directory, where most Linux distributions place their kernels.

        +

        You can continue to boot your computer with this type of configuration; however, the drawback is that you'll need to copy your kernel whenever it's updated. This can be a hassle. A better way is to configure you system so that the EFI, and therefore rEFInd, can read your Linux /boot directory, where most Linux distributions place their kernels. You do this by installing the appropriate EFI filesystem driver for the /boot (or root, /) filesystem.

        If You Need to Reconfigure Your Partitions....

        @@ -366,30 +366,60 @@ -
      1. rEFInd looks for an initial RAM disk in the same directory as the - kernel file. A matching initial RAM disk has a name that begins with +
      2. rEFInd looks for an initial RAM disk in the same directory as the kernel + file. A matching initial RAM disk has a name that begins with init and that includes the same version string as the kernel. - The version string is defined as the part of the filename from the - first digit to the last digit, inclusive. Note that the version string - can include non-digits. For instance, the version string for + The version string is defined as the part of the filename from the first + digit to the last digit, inclusive. Note that the version string can + include non-digits. For instance, the version string for bzImage-3.19.0.efi is 3.19.0, which matches initramfs-3.19.0.bz; and vmlinuz-4.2.5-300.fc23.x86_64's version string is 4.2.5-300.fc23.x86_64, which matches initrd-4.2.5-300.fc23.x86_64.img. Many other matches are - possible. If an initial RAM disk is identified, rEFInd passes a - suitable initrd= option to the kernel when it boots.
      3. + possible. If an initial RAM disk is identified, rEFInd passes a suitable + initrd= option to the kernel when it boots. There are two + variants on this rule: + +
          + +
        • As an extension to the preceding point, if multiple initial RAM disk + files match one kernel, the one whose filename matches the most + characters after the version string is used. For instance, suppose + the kernel filename is vmlinuz-4.8.0-32-standard, and two + initial RAM disk files are initrd-4.8.0-32-standard and + initrd-4.8.0-32-debug. The first of those files has nine + matching characters after the version string (-standard), + vs. just one matching character (-) for the second. Thus, + the first file will be used.
        • + +
        • If the refind_linux.conf file (described next) is present, + and if an initrd= specification is present for the option + you're using, rEFInd will not add a pointer to the initial + RAM disk file that it discovers. This feature enables you to + override rEFInd's initial RAM disk discovery. This is most useful in + Arch Linux, which can be configured with two different initial RAM + disk files, one to be used for normal booting and one for recovery + situations. You can specify each initial RAM disk file on its own + line, which gives you the ability to control which to use at boot + time.
      4. rEFInd looks for a file called refind_linux.conf in the same - directory as the kernel file. 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. If - you installed rEFInd with the refind-install - script, that script created a sample refind_linux.conf file, - customized for your computer, in /boot. This file will work - without changes on many installations, but you may need to tweak it for - some.
      5. + directory as the kernel file. 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. If you installed + rEFInd with the refind-install script, that script created a + sample refind_linux.conf file, customized for your computer, in + /boot. This file will work without changes on many + installations, but you may need to tweak it for some. If the kernel + options string includes the substring %v, rEFInd substitutes + the kernel version number for that string. (If you need the actual + string %v in your kernel options, use %%v instead; + rEFInd will change this to %v.) This feature can be used to + match an initial RAM disk file that requires special treatment, such as + if you have multiple numbered kernels, each of which has two initial RAM + disk files.
      6. If rEFInd can't find a refind_linux.conf file in the directory that holds the kernel, the program looks for a file called @@ -408,7 +438,7 @@
      7. If rEFInd can't find a refind_linux.conf file or an /etc/fstab file, it tries to identify the Linux root - (/ filesystem by looking for a partition with a GUID type code + (/) filesystem by looking for a partition with a GUID type code matching that specified for the root (/) filesystem in the Freedesktop.org Discoverable Partitions Specification. These type codes are as yet @@ -469,7 +499,8 @@
      8. All the kernels in a given directory use the same refind_linux.conf file. If you need to set different options for different kernels, you'll need to place those kernels in different - directories.
      9. + directories. (A partial exception is the kernel version string, which + can be passed via the %v variable, as noted earlier.)
      10. You must place your kernels in a directory other than the one that holds the main rEFInd .efi file. This is because rEFInd does @@ -489,7 +520,7 @@
        -

        copyright © 2012–2016 by Roderick W. Smith

        +

        copyright © 2012–2017 by Roderick W. Smith

        This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

        Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/docs/refind/mac-theme.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/docs/refind/mac-theme.png differ diff -Nru refind-0.10.4/docs/refind/mkrlconf.html refind-0.11.2/docs/refind/mkrlconf.html --- refind-0.10.4/docs/refind/mkrlconf.html 2016-10-09 23:12:55.000000000 +0000 +++ refind-0.11.2/docs/refind/mkrlconf.html 2017-10-22 20:40:56.000000000 +0000 @@ -4,7 +4,7 @@ Man page of MKRLCONF

        MKRLCONF

        -Section: rEFInd Manual (8)
        Updated: 0.10.4
        Index +Section: rEFInd Manual (8)
        Updated: 0.11.2
        Index Return to Main Contents
          @@ -90,6 +90,6 @@ This document was created by man2html, using the manual pages.
        -Time: 23:12:55 GMT, October 09, 2016 +Time: 20:40:56 GMT, October 22, 2017 Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/docs/refind/msinfo32.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/docs/refind/msinfo32.png differ diff -Nru refind-0.10.4/docs/refind/mvrefind.html refind-0.11.2/docs/refind/mvrefind.html --- refind-0.10.4/docs/refind/mvrefind.html 2016-10-09 23:12:55.000000000 +0000 +++ refind-0.11.2/docs/refind/mvrefind.html 2017-10-22 20:40:56.000000000 +0000 @@ -4,7 +4,7 @@ Man page of MVREFIND

        MVREFIND

        -Section: rEFInd Manual (8)
        Updated: 0.10.4
        Index +Section: rEFInd Manual (8)
        Updated: 0.11.2
        Index Return to Main Contents
          @@ -145,6 +145,6 @@ This document was created by man2html, using the manual pages.
        -Time: 23:12:55 GMT, October 09, 2016 +Time: 20:40:56 GMT, October 22, 2017 diff -Nru refind-0.10.4/docs/refind/refind-install.html refind-0.11.2/docs/refind/refind-install.html --- refind-0.10.4/docs/refind/refind-install.html 2016-10-09 23:12:55.000000000 +0000 +++ refind-0.11.2/docs/refind/refind-install.html 2017-10-22 20:40:56.000000000 +0000 @@ -4,7 +4,7 @@ Man page of REFIND-INSTALL

        REFIND-INSTALL

        -Section: rEFInd Manual (8)
        Updated: 0.10.4
        Index +Section: rEFInd Manual (8)
        Updated: 0.11.2
        Index Return to Main Contents
          @@ -18,7 +18,7 @@ [--notesp | --usedefault device-file | --root mount-point | --ownhfs device-file ] [--keepname] [--nodrivers | --alldrivers] -[--shim shim-filename] [--localkeys] [--yes] +[--shim shim-filename] [--localkeys] [--encryptkeys] [--yes]

          @@ -268,6 +268,21 @@ is readily available in most distributions' repositories, but the latter is not, so this option is not the default.

        +

        --encryptkeys + +
        +Ordinarily, if you use the --localkeys option, refind-install +stores the local key files on your hard disk in an unencrypted form. Thus, +should your computer be compromised, the intruder could use your own key to +sign a modified boot loader, eliminating the benefits of Secure Boot. If you +use this option, then the private key is stored in an encrypted form, +secured via an encryption password. You must enter this password before the +key can be used to sign any binary, thus reducing the risk that an intruder +could hijack your boot process. This is obviously a highly desirable option, +but the downside is that you must remember the password and enter it +whenever you update rEFInd or any other program signed with your private +key. This also makes a fully automated update of rEFInd impossible. +

        --keepname
        @@ -332,6 +347,6 @@ This document was created by man2html, using the manual pages.
        -Time: 23:12:55 GMT, October 09, 2016 +Time: 20:40:56 GMT, October 22, 2017 Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/docs/refind/rEFInd-Metro.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/docs/refind/rEFInd-Metro.png differ diff -Nru refind-0.10.4/docs/refind/refind-mkdefault.html refind-0.11.2/docs/refind/refind-mkdefault.html --- refind-0.10.4/docs/refind/refind-mkdefault.html 2016-10-09 23:12:55.000000000 +0000 +++ refind-0.11.2/docs/refind/refind-mkdefault.html 2017-10-22 20:40:56.000000000 +0000 @@ -4,7 +4,7 @@ Man page of REFIND-MKDEFAULT

        REFIND-MKDEFAULT

        -Section: rEFInd Manual (8)
        Updated: 0.10.4
        Index +Section: rEFInd Manual (8)
        Updated: 0.11.2
        Index Return to Main Contents
          @@ -201,6 +201,6 @@ This document was created by man2html, using the manual pages.
        -Time: 23:12:55 GMT, October 09, 2016 +Time: 20:40:56 GMT, October 22, 2017 diff -Nru refind-0.10.4/docs/refind/revisions.html refind-0.11.2/docs/refind/revisions.html --- refind-0.10.4/docs/refind/revisions.html 2016-10-09 22:56:04.000000000 +0000 +++ refind-0.11.2/docs/refind/revisions.html 2017-10-22 20:32:34.000000000 +0000 @@ -16,7 +16,7 @@

        by Roderick W. Smith, rodsmith@rodsbooks.com

        -

        Last Web page update: 10/9/2016

        +

        Last Web page update: 10/9/2017

        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!

        @@ -126,6 +126,357 @@
          +
        • 0.11.2 (10/22/2017) + +
        • I've fixed a bug, introduced in version 0.11.1, that caused setting + volumes in manual boot stanzas to not work.
        • + +
        • I've fixed a bug, present since version 0.11.0, that caused the new + tag-hiding feature to not work unless it was explicitly enabled in + refind.conf. (It should have been enabled by default.)
        • + +
        +
      11. + +
      12. 0.11.1 (10/9/2017)—This version is mainly a maintenance + release in response to Apple's release of macOS 10.13 ("High Sierra"), + although there are a couple of unrelated improvements. Its specific + changes are: +
          + +
        • The new Apple Filesystem (APFS) uses subvolumes, which appear as + subdirectories with UUIDs as names to the EFI and EFI programs such + as rEFInd. This fact means that the location of Apple's boot loader + has changed, from rEFInd's perspective, necessitating a code + update. This version provides that update.
        • + +
        • As a follow-on to the preceding change, I discovered that compiling + rEFInd with GNU-EFI resulted in a failure to properly track some + files on APFS volumes. I don't know if this failure reflected a bug + in Apple's EFI, in GNU-EFI, or in rEFInd; but I changed the way + rEFInd tracks boot loader files internally to work around the + problem. Although I've tested this version on an unusually wide + number of computers, it's possible that this change will introduce + new bugs. Thus, if you upgrade and have problems with boot loaders + not being detected or not launching, dropping back to version 0.11.0 + may be worth trying. (Be sure to contact me with a bug + report, too!)
        • + +
        • I've modified refind-install to be smarter about modifying + existing NVRAM entries for rEFInd under Linux. Previously, + refind-install was quite aggressive about deleting and + re-creating these entries; however, this was causing failures on a + few computers. The script now checks more carefully to see if an + existing entry boots rEFInd and is set as the default; and if so, it + leaves that entry alone.
        • + +
        • I fixed a bug that could cause the hidden-tag maintenance feature to + crash the program.
        • + +
        • I fixed a bug, introduced in version 0.11.0, that caused both Apple + and Microsoft second-row recovery tools to go undiscovered.
        • + +
        + +
      13. 0.11.0 (8/13/2017)—In addition to a few bug fixes, + this version sees several new features, many of which are likely + to be important to a significant number of people.... +
          + +
        • CJ Vaughter has improved his touch-screen code. This should both + make more tablets' touch screens work and expands the support to + work with mice. Both input methods are disabled by default; you must + enable one by uncommenting the enable_touch or + enable_mouse options in refind.conf. (Enable only + one of these features, though; they're mutually exclusive!) + If you enable mouse support, the mouse_speed and + mouse_size options affect the mouse tracking speed and the + size of the mouse pointer, too. Note that not all computers support + mouse input, much less touch input. The former seems to be largely + unrelated to whether the firmware's own user interface supports + mice, in my testing. If you enable one of these features and your + computer doesn't support it, you can still use rEFInd; but you may + see a useless mouse pointer, and the default selection may not come + up in a highlighted state. Also, these features do not work on + 32-bit systems.
        • + +
        • You can now hide OSes and external tool tags from the rEFInd main + menu by pressing the minus key (-) or Delete key (on PC + keyboards; some third-party Mac keyboards label this key Del, but + most Apple keyboards lack this key entirely). If you accidentally + hide a loder, you can recover it using the new tag recovery tool, + which uses a recycle icon on the second row. Hiding or un-hiding + loaders relies on the hidden_tags option being set on the + showtools line; but if you hide a tag and then remove the + hidden_tags option, rEFInd will continue to honor the + hidden settings. This option is set by default, but if you've edited + showtools for a previous installation and upgrade rEFInd, + you'll need to add hidden_tags to use this new + feature.
        • + +
        • A new refind.conf option, dont_scan_tools, works + much like dont_scan_files, but applies to external tools + (shells, MokManager binaries, etc.). You can use this option to hide + duplicate external tools.
        • + +
        • Thanks to Pavel Penev, the refind-install script now + supports a new option, --encryptkeys, which causes it to + encrypt and password-protect its local Secure Boot public key. This + option is useful only in conjunction with --localkeys. This + feature should help prevent abuse should somebody break into your + computer; the intruder won't be able to sign malware with your own + key and insert it into your boot path. You must set and remember a + password if you use this feature, though.
        • + +
        • The refind-install and mvrefind scripts now create + a file called BOOT.CSV and place it in the directory where + rEFInd is installed. This file is used by the fallback.efi + (aka fbx64.efi) program, which Fedora and some other + distributions are now installing, to regenerate a working boot list + should the NVRAM-based boot order be lost. See the page on keeping rEFInd booting for more on how to + control this functionality.
        • + +
        • Disk partitions can now be identified by partition GUID values in + more places—namely, in dont_scan_dirs and + dont_scan_files. Note that the GUIDs are partition + GUIDs, which some Linux tools identify as PARTUUID values. + Filesystem UUIDs are different. Partition GUIDs are fundamentally + GPT features; they don't exist on MBR disks. rEFInd assigns one + "fake" partition GUID to all MBR partitions, so MBR partitions can + be referred to, but cannot be distinguished from one another, in + this way.
        • + +
        • Identifying partitions by filesystem number (e.g., fs0: or + fs2:), which was deprecated with version 0.8.7 in 2015, is + now no longer supported—the relevant code has been removed. + You now must use filesystem labels, partition names, or + partition GUIDs instead of the unreliable filesystem numbers.
        • + +
        • In the past, some error messages on Macs would never appear on the + display, sometimes including a prompt to press a key to continue, + which could make it seem as if rEFInd had hung. rEFInd now includes + new features that enable such messages to appear in most (but + not yet all) cases, so you're less likely to see mysterious hangs + that aren't quite hangs on Macs. This does not affect UEFI-based + PCs.
        • + +
        • I've fixed a bug that caused disk badges to not be scaled along with + the main loader tag.
        • + +
        • Apple has updated at least some EFIs in a way that broke the + spoof_osx_version feature. This has been fixed.
        • + +
        • I've fixed a bug that caused rEFInd to ignore references to the + fallback boot loader (EFI/BOOT/bootx64.efi) in + dont_scan_files in some cases.
        • + +
        • I've fixed a bug in mvrefind that caused it to not restore + EFI/BOOT-rEFIndBackup when moving rEFInd out of the + EFI/BOOT location.
        • + +
        • I've fixed a bug that caused rEFInd to not properly sort a + Fedora/CentOS/RHEL vmlinuz-0-rescue* kernel to the bottom + of the kernel list.
        • + +
        +
      14. + +
      15. 0.10.9 (7/30/2017)—This version sees changes in some + graphics features and in the build process.... +
          + +
        • To better support HiDPI/retina displays, rEFInd now automatically + scales its icons and text to twice the usual size on displays wider + than 1920 pixels. This change does not affect text mode (for + which setting the textmode option in refind.conf + is still necessary. Explicitly setting either + small_icon_size or big_icon_size in + refind.conf disables this feature, so you can explicitly + set any icon or font size you like in the usual way.
        • + +
        • rEFInd now displays its background/banner image before scanning for + boot loaders, and displays a notice that it's scanning for boot + loaders at this time. This will barely be noticeable on most + systems, but if you have lots of OSes or kernels, you may notice the + change.
        • + +
        • On rare occasion, when rEFInd runs into a problem, it displays a + text-mode error message and prompts the user to continue, even when + it's operating in text mode. On Macs, this has caused what looks + like a hang, since this text would not be displayed, but the pause + for user input would still occur. rEFInd now at least displays the + prompt to continue, although the error text may not appear. (This + feature still needs more work.)
        • + +
        • I've added icons for the Trusty (14.04), Xenial (16.04), and Zesty + (17.04) versions of Ubuntu, for those who install multiple Ubuntu + versions and want to distinguish them by separate icons. Sooner or + later I'm likely to remove these icons as their versions reach + end-of-life status.
        • + +
        • I've updated the LodePNG library, which rEFInd uses to load PNG + images. This is unlikely to have any obvious effects for users.
        • + +
        • I've significantly reworked the build process when using the + TianoCore toolkit. In brief, in addition to the tiano + target for make, a new edk2 target exists, which + works with newer versions of TianoCore. Behind the scenes, the new + version builds rEFInd in a way that's more akin to what most + TianoCore projects use. See the BUILDING.txt file for + details. I'm also building most of my own binary packages with + UDK2017 rather than UDK2014, which I'd been using for the past few + years. (My PPA packages still use GNU-EFI.)
        • + +
        • My USB flash drive and CD-R images now include the gdisk + and gptsync binaries, although the latter is inactive by + default, even on Macs.
        • + +
        +
      16. + +
      17. 0.10.8 (5/21/2017)—This version's changes are modest, + although a couple will be important to a few users.... +
          + +
        • I've added shimx64.efi.signed as a valid Shim filename, and + mmx64.efi.signed as a valid MokManager filename, to + refind-install, so that Ubuntu users can point to the + signed Shim binaries on their root (/) partition, rather + than a copy on their ESP.
        • + +
        • I've made changes to enable compilation with GNU-EFI 3.0.5, which + was failing with the previous version.
        • + +
        • I've added an icon for Devuan GNU+Linux (a Debian spinoff that does + not use systemd).
        • + +
        • I've made some minor code efficiency improvements. These are + unlikely to have a noticeable impact on performance by + themselves.
        • + +
        • I've enabled the use of partition unique GUID values with + dont_scan_volumes. This should help users keep duplicate + boot loaders from showing up on RAID 1 arrays.
        • + +
        • I've changed "OS X" to "macOS" in assorted on-screen messages, to + conform with Apple's name change as of macOS 10.12 (Sierra). Note + that this change may require updating default_selection + options that rely on the string OS X!
        • + +
        +
      18. + +
      19. 0.10.7 (4/17/2017)—Soon after releasing version + 0.10.6, I discovered a potentially serious bug it introduced, and + so I've made this new release, with the following new features: +
          + +
        • Although the memory management bug introduced with version 0.10.6 + seems to be harmless on most systems, it caused hangs on one + computer (using UEFI DUET), hence my rushing out this update.
        • + +
        • I've answered too many queries from people who are confused by the + fact that many OS X installations are identified as Boot OS X + from Recovery HD on the rEFInd menu. Apple puts the boot loader + for its regular installation on the Recovery HD volume if + you use LVM or encrypt your root (/) partition, so rEFInd's + identification is correct, but it confuses people. I've therefore + adjusted rEFInd to omit the from Recovery HD part of that + message.
        • + +
        • I've updated refind-install to recognize mmx64.efi + (or the equivalent for other architectures) as an alternative name + for MokManager.efi.
        • +
        +
      20. + +
      21. 0.10.6 (4/16/2017)—This version includes a few small + bug fixes and one new feature: +
          + +
        • The new feature is the extra_kernel_version_strings token + in refind.conf. This token accepts a comma-delimited list + of strings that will be treated similarly to digits for purposes of + matching Linux initrd files to Linux kernels. See the description on + the Configuring the Boot Manager page + for details.
        • + +
        • Some distributions have renamed MokManager.efi to + mmarch.efi (where arch is an + architecture code, such as x64). I've adjusted rEFInd to + recognize MokManager under this new name. I've also added + fbarch.efi to the list of loaders that are not + scanned by default. This loader restores a machine's NVRAM-based EFI + boot manager entries from a backup file and then launches the + default boot loader.
        • + +
        • I've squashed a bug that could cause filesystems managed by rEFInd's + filesystem drivers to not be mounted.
        • + +
        • I've fixed a bug in mvrefind that would cause it to fail to + move a rEFInd installation if the target directory did not exist. + The script now creates the specified target, if necessary.
        • + +
        • Previously, rEFInd would explicitly set the video mode when it + started, even when the display was already running in that mode. + This version no longer does so. This is a shot-in-the-dark attempt + to work around problems on Macs with "retina" displays, which tend + to boot up in suboptimal resolutions when rEFInd is used.
        • + +
        +
      22. + +
      23. 0.10.5 (3/4/2017)—This version includes a number of + modest changes, most of which will be of interest to relatively few + people: +
          + +
        • The touch/tablet support has been improved and so may work with + a few more systems.
        • + +
        • The refind-install script has been updated to work better + with disks other than those whose names take the form + /dev/sd? and /dev/hd? (in Linux).
        • + +
        • For the benefit of new Apple laptops that lack physical Esc and + function keys, additional keybindings have been added: Backspace + (Delete on most Mac keyboards) now works the same as Esc, and Tab + now works the same as F2/Insert/+.
        • + +
        • The Linux initial RAM disk detection code has been expanded so that, + if two initial RAM disk files are found for a kernel, the one with + more characters after the version string that match the equivalent + characters in the kernel filename will be used. For instance, + suppose the kernel filename is vmlinuz-4.8.0-32-standard, + and two initial RAM disk files are + initrd-4.8.0-32-standard and + initrd-4.8.0-32-debug. The first of those files has nine + matching characters after the version string (-standard), + vs. just one matching character (-) for the second. Thus, + the first file will be used.
        • + +
        • A second change to Linux initial RAM disk detection is that you can + now specify the kernel version string with the string %v in + the refind_linux.conf file's options field. Thus, if your + distribution provides two initial RAM disk files per kernel, and + also provides numbered kernels, you can create a + refind_linux.conf file that enables you to boot with either + (or both) of the initial RAM disk files that match a specific + kernel.
        • + +
        • I've done some minor code optimization in the functions that search + for boot loaders. This had no noticeable effect on speed for me, and + is likely to be more than offset by the more complex initial RAM + disk processing noted above; but it might help a little bit on + systems with many boot loaders or kernels.
        • + +
        +
      24. +
      25. 0.10.4 (10/9/2016)—The number of changes in this version is modest, but some features are important to some people: @@ -443,7 +794,7 @@
        -

        copyright © 2012–2016 by Roderick W. Smith

        +

        copyright © 2012–2017 by Roderick W. Smith

        This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

        diff -Nru refind-0.10.4/docs/refind/secureboot.html refind-0.11.2/docs/refind/secureboot.html --- refind-0.10.4/docs/refind/secureboot.html 2016-10-09 22:46:18.000000000 +0000 +++ refind-0.11.2/docs/refind/secureboot.html 2017-10-22 20:29:02.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

        Originally written: 11/13/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

        +10/22/2017, referencing rEFInd 0.11.2

        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!

        @@ -531,7 +531,7 @@
        -

        copyright © 2012–2016 by Roderick W. Smith

        +

        copyright © 2012–2017 by Roderick W. Smith

        This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

        diff -Nru refind-0.10.4/docs/refind/sip.html refind-0.11.2/docs/refind/sip.html --- refind-0.10.4/docs/refind/sip.html 2016-10-09 17:15:25.000000000 +0000 +++ refind-0.11.2/docs/refind/sip.html 2017-10-22 20:13:27.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

        Originally written: 11/8/2015; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

        +10/22/2017, referencing rEFInd 0.11.2

        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!

        @@ -193,6 +193,8 @@
      26. At the startup chime, hold down the Command+R key combination. The computer should launch into the Recovery system. This is a very bare system, with only a window providing a way to launch a handful of utilities and a menu bar. You must use the latter.
      27. + +
      28. Select Utilities -> Terminal from the menu bar. A Terminal window should open.
      29. If you unpacked rEFInd on a USB flash drive, insert it and wait for its access light (if it has one) to stop blinking.
      30. @@ -201,7 +203,7 @@
      31. Type df -h in the Terminal. This produces a list of partitions that are mounted. Locate the one on which you unpacked the rEFInd files. It will normally be /Volumes/Somename, where Somename is the volume's name.
      32. -
      33. In the Terminal, use cd to change to the directory where the rEFInd files you unpacked earlier are stored. For instance, on my MacBook, I would type cd /Volumes/Macintosh\ HD/Users/rodsmith/Destkop/refind-0.10.2. Note that if any element of this path includes a space, you must either enclose the entire path in quotes or precede the space with a backslash (\), as in this example's Macintosh\ HD volume name.
      34. +
      35. In the Terminal, use cd to change to the directory where the rEFInd files you unpacked earlier are stored. For instance, on my MacBook, I would type cd /Volumes/Macintosh\ HD/Users/rodsmith/Desktop/refind-0.10.2. Note that if any element of this path includes a space, you must either enclose the entire path in quotes or precede the space with a backslash (\), as in this example's Macintosh\ HD volume name.
      36. Type ls to verify that refind-install is present in this directory.
      37. @@ -324,7 +326,7 @@
        -

        copyright © 2015-2016 by Roderick W. Smith

        +

        copyright © 2015–2017 by Roderick W. Smith

        This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

        diff -Nru refind-0.10.4/docs/refind/themes.html refind-0.11.2/docs/refind/themes.html --- refind-0.10.4/docs/refind/themes.html 2016-10-09 22:45:33.000000000 +0000 +++ refind-0.11.2/docs/refind/themes.html 2017-10-22 20:28:53.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

        Originally written: 4/19/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

        +10/22/2017, referencing rEFInd 0.11.2

        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!

        @@ -293,15 +293,11 @@
      38. ecto-plazm's theme was one of the first independent themes to be created for rEFInd.
      39. -
      40. The Gris Theme (also available as an Arch Linux package) uses a minimalistic white-on-gray design:
      41. +
      42. The Mac theme was created by Wesley Turner-Harris, and is a theme with relatively few icons intended for use on Macs. See Wesley's Web site if you want to contact the creator of this theme.
      43. -
        Gris uses a minimalistic white-on-gray
-    color scheme

        - -
      44. The Mac theme was created by Wesley Turner-Harris. See Wesley's Web site if you want to contact the creator of this theme.
      45. +
        The Mac theme is designed for use on
+    Macs

      46. Evan Purkhiser's Minimal theme uses black icons on a gray background of varied brightness, as shown here:
      47. @@ -310,6 +306,12 @@ src="https://camo.githubusercontent.com/999cff82d4bea54f222e165d647b5df597f45b86/687474703a2f2f692e696d6775722e636f6d2f33624d473655372e706e67" align="center" width="750" alt="Minimal uses flat icons and a subtly-graded background" border=2>
        +
      48. John Trenton Cary's rEFInd Metro theme is another minimal theme. It uses a solid background color and a number of OS icons.
      49. + +
        rEFInd Next uses simple white icons against green artwork

        +
      50. Sean Gibbons' rEFInd Next theme is "inspired by both iOS 7 and Windows 8 interfaces." It includes both a background image and a number of OS icons.

      51. A clean theme with a light background

        -
      52. Nitrofurano has posted a 1970s-inspired theme on opendesktop.org.
      53. +
      54. Despite its name, the Tux Boot Loader Theme for Ubuntu can be used with any Linux distribution (or on a system without Linux installed at all).
      55. -
        Like disco and John Travolta? Maybe
-    this theme is for you!

        +
        A theme with
+    a dark background and icons with a disk-icon theme +

        + +
      56. The rEFInd Ambience Theme is another one with minimalistic icons against a shaded background.
      57. + +
        A theme with
+    a shaded background and simple icons +

        @@ -362,7 +370,7 @@
        -

        copyright © 2012–2016 by Roderick W. Smith

        +

        copyright © 2012–2017 by Roderick W. Smith

        This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

        diff -Nru refind-0.10.4/docs/refind/todo.html refind-0.11.2/docs/refind/todo.html --- refind-0.10.4/docs/refind/todo.html 2016-10-09 22:58:07.000000000 +0000 +++ refind-0.11.2/docs/refind/todo.html 2017-10-22 20:28:55.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

        Originally written: 3/14/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

        +10/22/2017, referencing rEFInd 0.11.2

        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!

        @@ -234,24 +234,26 @@
      58. I've been receiving reports of blank screens when using rEFInd on some recent Mac models. I've investigated this with the help of one - user, and I suspect that Apple has made changes to its firmware - that are likely to affect just about any EFI program. I don't have - a definitive solution, but at least one user has reported that + user, and I suspect that Apple has made changes to its firmware that + are likely to affect just about any EFI program. I don't have a + definitive solution, but at least one user has reported that removing rEFInd's drivers has caused the problem to go into - remission.
      59. + remission. Changes made in version 0.11.0 improve error reporting on + Macs, which may help with this issue.
      60. Another Mac-specific display problem relates to "retina" displays: Some users report that rEFInd comes up in a lower resolution than the screen supports, and that this setting persists into the running OS X instance, and can't be adjusted using the usual OS X means. - Unfortunately, I lack the hardware necessary to experiment and find - a solution to this problem within rEFInd. Thus, a fix will have to - wait for me to get my hands on such hardware (which is not on my - immediate purchase list) or until somebody with such hardware and - the necessary skills submits a fix. (Note that a fix could - conceivably involve passing options to the OS X boot loader or - something else that would require trivial or no changes to - rEFInd.)
      61. + I've just recently (mid-2017) purchased an iMac with a "retina" + display, so I can now begin to investigate this problem, but as of + rEFInd 0.11.0, I haven't yet had a chance to look into it in depth. + I've heard that this problem affects not just rEFInd, but also GRUB, + and even Windows when dual-booting on a Mac; see this YouTube video + and This + AskUbuntu question and answers, for instance.
      62. Some EFIs have bugs that cause the allegedly case-insensitive StriCmp() function to perform a case-sensitive comparison. @@ -277,13 +279,12 @@
      63. A couple of Mac users have reported that the brightness-adjustment features in Windows don't work when Windows is booted via rEFInd, - but that these features do work when Windows is booted via the - Mac's built-in boot manager. Unfortunately, I have no idea what - causes this problem, I have no Windows installation on my one - (elderly) Mac, and I have no way to debug it. Therefore, it's - unlikely that I'll be able to fix this problem myself; but if you - have the equipment and skill to do so, I'd be interested in - receiving a patch.
      64. + but that these features do work when Windows is booted via the Mac's + built-in boot manager. Unfortunately, I have no idea what causes + this problem, I have no Windows installation on my Macs, and I have + no way to debug it. Therefore, it's unlikely that I'll be able to + fix this problem myself; but if you have the equipment and skill to + do so, I'd be interested in receiving a patch.
      65. If you use a true MBR disk on a Mac to boot Windows or some other BIOS-only OS, and if that disk has an extended partition, bogus @@ -296,10 +297,10 @@ ignoring new media or keeping old media that have been ejected. This should be investigated and fixed.
      66. -
      67. The "scanning for new boot loaders" message that appears during the - re-scan feature is primitive. Some sort of dynamic icon would be - nice, but perhaps impractical, given the single-tasking nature of - EFI.
      68. +
      69. The "scanning for boot loaders" message that appears at startup and + during the re-scan feature is primitive. Some sort of dynamic icon + would be nice, but perhaps impractical, given the single-tasking + nature of EFI.
      70. On my Mac Mini, launching a shell, returning, and performing a re-scan causes the system to be unable to launch the shell again. I @@ -312,33 +313,41 @@ in the actual volume name read from disk. Thus, you can't specify a volume by name if it includes a slash (as in Fedora /boot). Workarounds are to rename the volume to omit the slash - and to use a filesystem number rather than a volume label.
      71. + and to use a partition GUID rather than a volume label.
      72. The code is in need of review to search for memory leaks and similar problems.
      73. -
      74. If the user has a Linux software RAID 1 array with Btrfs, HFS+, - or FAT filesystem, rEFInd will detect kernels or boot loaders in - RAID 1 twice. Checks to prevent this with ext2/3/4fs and ReiserFS - already exist; these checks could be expanded to block such - duplication with more filesystems.
      75. +
      76. If the user has a Linux software RAID 1 array with Btrfs, HFS+, or + FAT filesystem, rEFInd will detect kernels or boot loaders in RAID 1 + twice. Checks to prevent this with ext2/3/4fs and ReiserFS already + exist; these checks could be expanded to block such duplication with + more filesystems. Using the in-rEFInd hiding feature (activated by + the Delete or minus [-] key) can remove a redundant + entry.
      77. Some Macs experience problems with waking up from suspend states - when rEFInd is installed. Unfortunately, I lack the hardware to - test and experiment with this (my only Intel-based Mac doesn't - exhibit this problem), so I can't fix this myself. Using - pmset to disable the autopoweroff option is - pmset to disable the autopoweroff option is claimed - by some to at least partially fix the problem, though. Using - the --ownhfs installation option may also help in some + by some to at least partially fix the problem, though. Using the + --ownhfs installation option may also help in some cases.
      78. If you activate BIOS-mode support on UEFI-based PCs, you may find multiple copies of the BIOS-mode loaders added to your firmware's boot manager. Only one copy shows up in rEFInd, though.
      79. +
      80. If you have a manual boot stanza for a Linux kernel with both an + initrd line and a second initrd file specified on the + options line, both initrd files will be passed to the + kernel in most situations; however, one will be omitted if + you enter the submenu (via F2, Insert, or Tab) and select the + default entry there. This bug is caused by the convoluted way rEFInd + generates its submenus, and I'm putting off fixing it until I can + give that code the overhaul it desperately needs.
      81. +
      82. New features I'd like to add: @@ -383,16 +392,17 @@ the NVRAM, and so on. This would be useful in system maintenance and in recovering from boot problems.
      83. -
      84. An installation tool for the EFI environment would be useful. - A simple EFI shell script might work, but because this function - requires access to the bcfg command, this would work - only from a version 2 shell or if bcfg were implemented - as a standalone program. Another alternative would be a program - written in C.
      85. - -
      86. It should be possible to override specific auto-detected boot - loader settings—say, to disable one specific boot loader or - change its icon.
      87. +
      88. An installation tool for the EFI environment would be useful. A + simple EFI shell script might work, but because this function + requires access to the bcfg command, this would work only + from a version 2 shell or if bcfg were implemented as a + standalone program. Another alternative would be a program written + in C. Since Python is now available in EFI, a Python-based script + might also work; but that would require installing Python.
      89. + +
      90. It should be possible to override specific auto-detected boot loader + settings—say, to change the icon for one specific boot + loader.
      91. A GUI configuration tool for host OSes (Linux, OS X, Windows, etc.) would be nice, but it's low on my personal priority list. If you'd @@ -449,6 +459,15 @@ BIOS-mode boot loader from some servers that offer both, which makes it useless on those networks.
      92. +
      93. The handling of encrypted local Secure Boot keys by + refind-install could be improved. Specifically, if you + install without encrypted keys and then run refind-install + with --encryptkeys, or vice-versa, the script is likely to + ask for keys repeatedly. Error handling (if an incorrect key is + entered, for instance) is also poor. If an encrypted key is used and + a rEFInd RPM or Debian package is installed, that installation may + fail to set things up correctly.
      94. +
      95. A Mac-specific package is highly desirable.
      96. @@ -457,7 +476,7 @@
        -

        copyright © 2012–2016 by Roderick W. Smith

        +

        copyright © 2012–2017 by Roderick W. Smith

        This document is licensed under the terms of the GNU Free Documentation License (FDL), version 1.3.

        Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/docs/refind/tux-refind-theme.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/docs/refind/tux-refind-theme.png differ Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/docs/refind/ucs2.txt and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/docs/refind/ucs2.txt differ diff -Nru refind-0.10.4/docs/refind/using.html refind-0.11.2/docs/refind/using.html --- refind-0.10.4/docs/refind/using.html 2016-10-09 17:15:49.000000000 +0000 +++ refind-0.11.2/docs/refind/using.html 2017-10-22 20:13:44.000000000 +0000 @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

        Originally written: 3/14/2012; last Web page update: -10/9/2016, referencing rEFInd 0.10.4

        +10/22/2017, referencing rEFInd 0.11.2

        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!

        @@ -196,7 +196,7 @@ -

        Ordinarily, rEFInd displays tags for OSes it finds on internal hard disks, external hard disks (including USB flash drives, CF disks, and so on), and optical discs. Sometimes, though, the firmware hasn't had time to fully examine these devices by the time rEFInd starts; or you might only insert or plug in the media after rEFInd appears. In these cases, you can press the Esc key to have rEFInd re-read its configuration file and re-scan your media for boot loaders. This action can take a few seconds to complete, so be patient. You can also use this feature to detect OSes if you launch a shell and use it to load a driver or edit the refind.conf file. If you regularly need to press Esc, you might look into the scan_delay configuration file option, described on the Configuring the Boot Manager page.

        +

        Ordinarily, rEFInd displays tags for OSes it finds on internal hard disks, external hard disks (including USB flash drives, CF disks, and so on), and optical discs. Sometimes, though, the firmware hasn't had time to fully examine these devices by the time rEFInd starts; or you might only insert or plug in the media after rEFInd appears. In these cases, you can press the Esc or Backspace (Delete on Macs) key to have rEFInd re-read its configuration file and re-scan your media for boot loaders. This action can take a few seconds to complete, so be patient. You can also use this feature to detect OSes if you launch a shell and use it to load a driver or edit the refind.conf file. If you regularly need to press Esc/Backspace, you might look into the scan_delay configuration file option, described on the Configuring the Boot Manager page.

        On some computers, the firmware doesn't mount external USB media unless you adjust a firmware option or use the EFI's own boot manager prior to launching rEFInd. If you don't see external media appear in rEFInd's list, consult your computer's manual or examine its firmware to locate a relevant option. This option is often called fast boot or something similar; when enabled, the computer doesn't activate most USB devices because doing so takes a second or two.

        @@ -204,13 +204,13 @@

        Adjusting Boot Options

        -

        If you press the Insert, F2, or + key, rEFInd will show a menu that may hold additional options, depending on the OS type. (OS X and Linux are most likely to hold interesting options on their submenus.) The following figure shows the submenu for Mac OS X. You can use this menu much like the main menu; move the cursor to select the option you want to use, then press the Enter key to launch the boot loader with the selected options. Press the Esc key or select Return to Main Menu to return to the main menu. (See the Methods of Booting Linux page for information on what you might see on a Linux submenu page.)

        +

        If you press the Insert, F2, Tab, or + key, rEFInd will show a menu that may hold additional options, depending on the OS type. (OS X and Linux are most likely to hold interesting options on their submenus.) The following figure shows the submenu for Mac OS X. You can use this menu much like the main menu; move the cursor to select the option you want to use, then press the Enter key to launch the boot loader with the selected options. Press the Esc or Backspace (Delete on Macs) key or select Return to Main Menu to return to the main menu. (See the Methods of Booting Linux page for information on what you might see on a Linux submenu page.)


        rEFInd submenus enable you to set session-specific
     options.

        -

        From the options submenu, you can press the Insert, F2, or + key again to edit your boot loader options. You're most likely to want to do this when booting Linux via its EFI stub loader, since you can then enter arbitrary kernel options. A simple text-mode line editor opens (shown below), enabling you to move a cursor back and forth in the line with your arrow keys, delete text, and type in new text. If you want to boot with your edited options, press the Enter key. If you decide you picked the wrong entry, press the Esc key. Note that long option lists, as shown in the figure, scroll off the edge of the screen. Moving the cursor past the screen edge scrolls the entire line of text.

        +

        From the options submenu, you can press the Insert, F2, Tab, or + key again to edit your boot loader options. You're most likely to want to do this when booting Linux via its EFI stub loader, since you can then enter arbitrary kernel options. A simple text-mode line editor opens (shown below), enabling you to move a cursor back and forth in the line with your arrow keys, delete text, and type in new text. If you want to boot with your edited options, press the Enter key. If you decide you picked the wrong entry, press the Esc or Backspace key. Note that long option lists, as shown in the figure, scroll off the edge of the screen. Moving the cursor past the screen edge scrolls the entire line of text.


        You can edit options passed to the boot loader on a
@@ -263,11 +263,15 @@
    <td>Moves the selection to the last item on the utilities row</td>
 </tr>
 <tr>
-   <td><i>Esc</i></td>
+   <td><i>Esc</i> or <i>Backspace</i> (<i>Delete</i> on Mac keyboards)</td>
    <td>Returns from a sub-menu; on the main screen, re-reads the configuration file and re-scans for boot loaders</td>
 </tr>
 <tr>
-   <td><i>Insert</i>, <i>F2</i>, or <i>+</i></td>
+   <td><i>Delete</i> (on PCs) or minus (<i>-</i>) (<i>Delete</i> on Mac keyboards is <i>Backspace</i> on PC keyboards, and will not work for this)</td>
+   <td>Hides a menu tag. The tag is remembered via the computer's on-board NVRAM.</td>
+</tr>
+<tr>
+   <td><i>Insert</i>, <i>F2</i>, <i>Tab</i>, or <i>+</i></td>
    <td>From the main menu, opens the selection's submenu, which is most useful with Mac OS X, ELILO, and Linux kernels with EFI stub loader support; in a submenu, opens a line editor enabling editing of boot options</td>
 </tr>
 <tr>
@@ -384,7 +388,7 @@
 
 <hr />
 
-<p>copyright © 2012–2016 by Roderick W. Smith</p>
+<p>copyright © 2012–2017 by Roderick W. Smith</p>
 
 <p>This document is licensed under the terms of the <a href=GNU Free Documentation License (FDL), version 1.3.

        Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/docs/refind/utf16.txt and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/docs/refind/utf16.txt differ diff -Nru refind-0.10.4/EfiLib/DevicePath.c refind-0.11.2/EfiLib/DevicePath.c --- refind-0.10.4/EfiLib/DevicePath.c 2015-11-29 18:54:47.000000000 +0000 +++ refind-0.11.2/EfiLib/DevicePath.c 2017-05-15 00:15:04.000000000 +0000 @@ -31,7 +31,7 @@ CHAR16 * EFIAPI -CatPrint ( +MyCatPrint ( IN OUT POOL_PRINT *Str, IN CHAR16 *Fmt, ... @@ -94,7 +94,7 @@ PCI_DEVICE_PATH *Pci; Pci = DevPath; - CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function); + MyCatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function); } /** @@ -116,7 +116,7 @@ PCCARD_DEVICE_PATH *Pccard; Pccard = DevPath; - CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber); + MyCatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber); } /** @@ -138,7 +138,7 @@ MEMMAP_DEVICE_PATH *MemMap; MemMap = DevPath; - CatPrint ( + MyCatPrint ( Str, L"MemMap(%d:%lx-%lx)", (UINTN) MemMap->MemoryType, @@ -166,7 +166,7 @@ CONTROLLER_DEVICE_PATH *Controller; Controller = DevPath; - CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber); + MyCatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber); } @@ -202,30 +202,30 @@ Type = L"Msg"; /* if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) { - CatPrint (Str, L"VenPcAnsi()"); + MyCatPrint (Str, L"VenPcAnsi()"); return ; } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) { - CatPrint (Str, L"VenVt100()"); + MyCatPrint (Str, L"VenVt100()"); return ; } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) { - CatPrint (Str, L"VenVt100Plus()"); + MyCatPrint (Str, L"VenVt100Plus()"); return ; } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) { - CatPrint (Str, L"VenUft8()"); + MyCatPrint (Str, L"VenUft8()"); return ; } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid )) { FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap); switch (FlowControlMap & 0x00000003) { case 0: - CatPrint (Str, L"UartFlowCtrl(%s)", L"None"); + MyCatPrint (Str, L"UartFlowCtrl(%s)", L"None"); break; case 1: - CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware"); + MyCatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware"); break; case 2: - CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff"); + MyCatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff"); break; default: @@ -237,7 +237,7 @@ } else */ if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) { - CatPrint ( + MyCatPrint ( Str, L"SAS(%lx,%lx,%x,", ((SAS_DEVICE_PATH *) Vendor)->SasAddress, @@ -246,9 +246,9 @@ ); Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology); if ((Info & 0x0f) == 0) { - CatPrint (Str, L"NoTopology,0,0,0,"); + MyCatPrint (Str, L"NoTopology,0,0,0,"); } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) { - CatPrint ( + MyCatPrint ( Str, L"%s,%s,%s,", ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS", @@ -256,19 +256,19 @@ ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct" ); if ((Info & 0x0f) == 1) { - CatPrint (Str, L"0,"); + MyCatPrint (Str, L"0,"); } else { - CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff)); + MyCatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff)); } } else { - CatPrint (Str, L"0,0,0,0,"); + MyCatPrint (Str, L"0,0,0,0,"); } - CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved); + MyCatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved); return ; } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) { - CatPrint (Str, L"DebugPort()"); + MyCatPrint (Str, L"DebugPort()"); return ; } break; @@ -282,15 +282,15 @@ break; } - CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid); + MyCatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid); DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH); if (DataLength > 0) { - CatPrint (Str, L","); + MyCatPrint (Str, L","); for (Index = 0; Index < DataLength; Index++) { - CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]); + MyCatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]); } } - CatPrint (Str, L")"); + MyCatPrint (Str, L")"); } /** @@ -313,9 +313,9 @@ Acpi = DevPath; if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { - CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID); + MyCatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID); } else { - CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID); + MyCatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID); } } @@ -388,50 +388,50 @@ } if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) { - CatPrint (Str, L"AcpiExp("); + MyCatPrint (Str, L"AcpiExp("); if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { - CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID)); + MyCatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID)); } else { - CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID); + MyCatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID); } if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { - CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID)); + MyCatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID)); } else { - CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID); + MyCatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID); } if (UIDSTRIdx != 0) { - CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx); + MyCatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx); } else { - CatPrint (Str, L"\"\")"); + MyCatPrint (Str, L"\"\")"); } } else { - CatPrint (Str, L"AcpiEx("); + MyCatPrint (Str, L"AcpiEx("); if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { - CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID)); + MyCatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID)); } else { - CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID); + MyCatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID); } if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { - CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID)); + MyCatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID)); } else { - CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID); + MyCatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID); } - CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID); + MyCatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID); if (HIDSTRIdx != 0) { - CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx); + MyCatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx); } else { - CatPrint (Str, L"\"\","); + MyCatPrint (Str, L"\"\","); } if (CIDSTRIdx != 0) { - CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx); + MyCatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx); } else { - CatPrint (Str, L"\"\","); + MyCatPrint (Str, L"\"\","); } if (UIDSTRIdx != 0) { - CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx); + MyCatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx); } else { - CatPrint (Str, L"\"\")"); + MyCatPrint (Str, L"\"\")"); } } @@ -462,11 +462,11 @@ Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr); AdditionalAdrCount = (UINT16) ((Length - 8) / 4); - CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR); + MyCatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR); for (Index = 0; Index < AdditionalAdrCount; Index++) { - CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4)); + MyCatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4)); } - CatPrint (Str, L")"); + MyCatPrint (Str, L")"); } /** @@ -488,7 +488,7 @@ ATAPI_DEVICE_PATH *Atapi; Atapi = DevPath; - CatPrint ( + MyCatPrint ( Str, L"Ata(%s,%s)", (Atapi->PrimarySecondary != 0)? L"Secondary" : L"Primary", @@ -515,7 +515,7 @@ SCSI_DEVICE_PATH *Scsi; Scsi = DevPath; - CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun); + MyCatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun); } /** @@ -537,7 +537,7 @@ FIBRECHANNEL_DEVICE_PATH *Fibre; Fibre = DevPath; - CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun); + MyCatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun); } /** @@ -559,7 +559,7 @@ F1394_DEVICE_PATH *F1394Path; F1394Path = DevPath; - CatPrint (Str, L"1394(%lx)", &F1394Path->Guid); + MyCatPrint (Str, L"1394(%lx)", &F1394Path->Guid); } /** @@ -581,7 +581,7 @@ USB_DEVICE_PATH *Usb; Usb = DevPath; - CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber); + MyCatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber); } /** @@ -603,7 +603,7 @@ USB_WWID_DEVICE_PATH *UsbWWId; UsbWWId = DevPath; - CatPrint ( + MyCatPrint ( Str, L"UsbWwid(%x,%x,%x,\"WWID\")", (UINTN) UsbWWId->VendorId, @@ -631,7 +631,7 @@ DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; LogicalUnit = DevPath; - CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun); + MyCatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun); } /** @@ -653,7 +653,7 @@ USB_CLASS_DEVICE_PATH *UsbClass; UsbClass = DevPath; - CatPrint ( + MyCatPrint ( Str, L"Usb Class(%x,%x,%x,%x,%x)", (UINTN) UsbClass->VendorId, @@ -684,14 +684,14 @@ Sata = DevPath; if ((Sata->PortMultiplierPortNumber & SATA_HBA_DIRECT_CONNECT_FLAG) != 0) { - CatPrint ( + MyCatPrint ( Str, L"Sata(%x,%x)", (UINTN) Sata->HBAPortNumber, (UINTN) Sata->Lun ); } else { - CatPrint ( + MyCatPrint ( Str, L"Sata(%x,%x,%x)", (UINTN) Sata->HBAPortNumber, @@ -720,7 +720,7 @@ I2O_DEVICE_PATH *I2OPath; I2OPath = DevPath; - CatPrint (Str, L"I2O(%x)", (UINTN) I2OPath->Tid); + MyCatPrint (Str, L"I2O(%x)", (UINTN) I2OPath->Tid); } /** @@ -750,13 +750,13 @@ HwAddressSize = 6; } - CatPrint (Str, L"Mac("); + MyCatPrint (Str, L"Mac("); for (Index = 0; Index < HwAddressSize; Index++) { - CatPrint (Str, L"%02x", (UINTN) MACDevPath->MacAddress.Addr[Index]); + MyCatPrint (Str, L"%02x", (UINTN) MACDevPath->MacAddress.Addr[Index]); } - CatPrint (Str, L")"); + MyCatPrint (Str, L")"); } /** @@ -778,7 +778,7 @@ IPv4_DEVICE_PATH *IPDevPath; IPDevPath = DevPath; - CatPrint ( + MyCatPrint ( Str, L"IPv4(%d.%d.%d.%d:%d)", (UINTN) IPDevPath->RemoteIpAddress.Addr[0], @@ -808,7 +808,7 @@ IPv6_DEVICE_PATH *IPv6DevPath; IPv6DevPath = DevPath; - CatPrint ( + MyCatPrint ( Str, L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)", (UINTN) IPv6DevPath->RemoteIpAddress.Addr[0], @@ -849,7 +849,7 @@ INFINIBAND_DEVICE_PATH *InfiniBand; InfiniBand = DevPath; - CatPrint ( + MyCatPrint ( Str, L"Infiniband(%x,%g,%lx,%lx,%lx)", (UINTN) InfiniBand->ResourceFlags, @@ -911,36 +911,36 @@ } if (Uart->BaudRate == 0) { - CatPrint (Str, L"Uart(DEFAULT,%c,", Parity); + MyCatPrint (Str, L"Uart(DEFAULT,%c,", Parity); } else { - CatPrint (Str, L"Uart(%ld,%c,", Uart->BaudRate, Parity); + MyCatPrint (Str, L"Uart(%ld,%c,", Uart->BaudRate, Parity); } if (Uart->DataBits == 0) { - CatPrint (Str, L"D,"); + MyCatPrint (Str, L"D,"); } else { - CatPrint (Str, L"%d,", (UINTN) Uart->DataBits); + MyCatPrint (Str, L"%d,", (UINTN) Uart->DataBits); } switch (Uart->StopBits) { case 0: - CatPrint (Str, L"D)"); + MyCatPrint (Str, L"D)"); break; case 1: - CatPrint (Str, L"1)"); + MyCatPrint (Str, L"1)"); break; case 2: - CatPrint (Str, L"1.5)"); + MyCatPrint (Str, L"1.5)"); break; case 3: - CatPrint (Str, L"2)"); + MyCatPrint (Str, L"2)"); break; default: - CatPrint (Str, L"x)"); + MyCatPrint (Str, L"x)"); break; } } @@ -965,7 +965,7 @@ UINT16 Options; IScsi = DevPath; - CatPrint ( + MyCatPrint ( Str, L"iSCSI(%a,%x,%lx,", IScsi->TargetName, @@ -974,18 +974,18 @@ ); Options = IScsi->LoginOption; - CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None"); - CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None"); + MyCatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None"); + MyCatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None"); if (((Options >> 11) & 0x0001) != 0) { - CatPrint (Str, L"%s,", L"None"); + MyCatPrint (Str, L"%s,", L"None"); } else if (((Options >> 12) & 0x0001) != 0) { - CatPrint (Str, L"%s,", L"CHAP_UNI"); + MyCatPrint (Str, L"%s,", L"CHAP_UNI"); } else { - CatPrint (Str, L"%s,", L"CHAP_BI"); + MyCatPrint (Str, L"%s,", L"CHAP_BI"); } - CatPrint (Str, L"%s)", (IScsi->NetworkProtocol == 0) ? L"TCP" : L"reserved"); + MyCatPrint (Str, L"%s)", (IScsi->NetworkProtocol == 0) ? L"TCP" : L"reserved"); } /** @@ -1007,7 +1007,7 @@ VLAN_DEVICE_PATH *Vlan; Vlan = DevPath; - CatPrint (Str, L"Vlan(%d)", (UINTN) Vlan->VlanId); + MyCatPrint (Str, L"Vlan(%d)", (UINTN) Vlan->VlanId); } /** @@ -1031,7 +1031,7 @@ Hd = DevPath; switch (Hd->SignatureType) { case SIGNATURE_TYPE_MBR: - CatPrint ( + MyCatPrint ( Str, L"HD(Part%d,Sig%08x)", (UINTN) Hd->PartitionNumber, @@ -1040,7 +1040,7 @@ break; case SIGNATURE_TYPE_GUID: - CatPrint ( + MyCatPrint ( Str, L"HD(Part%d,Sig%g)", (UINTN) Hd->PartitionNumber, @@ -1049,7 +1049,7 @@ break; default: - CatPrint ( + MyCatPrint ( Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)", (UINTN) Hd->PartitionNumber, @@ -1079,7 +1079,7 @@ CDROM_DEVICE_PATH *Cd; Cd = DevPath; - CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry); + MyCatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry); } /** @@ -1101,7 +1101,7 @@ FILEPATH_DEVICE_PATH *Fp; Fp = DevPath; - CatPrint (Str, L"%s", Fp->PathName); + MyCatPrint (Str, L"%s", Fp->PathName); } /** @@ -1123,7 +1123,7 @@ MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; MediaProt = DevPath; - CatPrint (Str, L"Media(%g)", &MediaProt->Protocol); + MyCatPrint (Str, L"Media(%g)", &MediaProt->Protocol); } /** @@ -1145,7 +1145,7 @@ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; FvFilePath = DevPath; - CatPrint (Str, L"%g", &FvFilePath->FvFileName); + MyCatPrint (Str, L"%g", &FvFilePath->FvFileName); } /** @@ -1167,7 +1167,7 @@ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; Offset = DevPath; - CatPrint ( + MyCatPrint ( Str, L"Offset(%lx,%lx)", Offset->StartingOffset, @@ -1228,7 +1228,7 @@ Type = L"?"; break; } - CatPrint (Str, L"Legacy-%s", Type); + MyCatPrint (Str, L"Legacy-%s", Type); } /** @@ -1247,7 +1247,7 @@ IN VOID *DevPath ) { - CatPrint (Str, L","); + MyCatPrint (Str, L","); } /** @@ -1266,7 +1266,7 @@ IN VOID *DevPath ) { - CatPrint (Str, L"?"); + MyCatPrint (Str, L"?"); } /** Convert Device Path to a Unicode string for printing. @@ -1287,7 +1287,7 @@ MEDIA_FW_VOL_DEVICE_PATH *FvPath; FvPath = DevPath; - CatPrint (Str, L"Fv(%g)", &FvPath->FvName); + MyCatPrint (Str, L"Fv(%g)", &FvPath->FvName); } DEVICE_PATH_STRING_TABLE DevPathTable[] = { @@ -1553,7 +1553,7 @@ // Put a path seperator in if needed // if ((Str.Len != 0) && (DumpNode != DevPathEndInstance)) { - CatPrint (&Str, L"/"); + MyCatPrint (&Str, L"/"); } // // Print this node of the device path diff -Nru refind-0.10.4/EfiLib/GenericBdsLib.h refind-0.11.2/EfiLib/GenericBdsLib.h --- refind-0.10.4/EfiLib/GenericBdsLib.h 2015-12-05 14:24:59.000000000 +0000 +++ refind-0.11.2/EfiLib/GenericBdsLib.h 2017-05-15 00:15:04.000000000 +0000 @@ -872,11 +872,6 @@ @retval EFI_ACCESS_DENIED The user was not successfully identified. **/ -// EFI_STATUS -// EFIAPI -// BdsLibUserIdentify ( -// OUT EFI_USER_PROFILE_HANDLE *User -// ); /** This function checks if a Fv file device path is valid, according to a file GUID. If it is invalid, @@ -961,7 +956,7 @@ CHAR16 * EFIAPI -CatPrint ( +MyCatPrint ( IN OUT POOL_PRINT *Str, IN CHAR16 *Fmt, ... diff -Nru refind-0.10.4/EfiLib/gnuefi-helper.c refind-0.11.2/EfiLib/gnuefi-helper.c --- refind-0.10.4/EfiLib/gnuefi-helper.c 2015-11-29 18:54:47.000000000 +0000 +++ refind-0.11.2/EfiLib/gnuefi-helper.c 2017-08-06 02:19:05.000000000 +0000 @@ -21,7 +21,6 @@ #include "LegacyBios.h" EFI_GUID gEfiDevicePathUtilitiesProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -EFI_GUID gEfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }}; EFI_GUID gEfiLegacyBiosProtocolGuid = { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }}; /** @@ -154,13 +153,13 @@ IN UINTN MaxSize ) { - UINTN Count; +// UINTN Count; UINTN Size; UINTN NodeLength; ASSERT (DevicePath != NULL); - for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + for (/* Count = 0, */ Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { NodeLength = DevicePathNodeLength (DevicePath); if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { return FALSE; diff -Nru refind-0.10.4/EfiLib/legacy.c refind-0.11.2/EfiLib/legacy.c --- refind-0.10.4/EfiLib/legacy.c 2015-11-29 18:54:47.000000000 +0000 +++ refind-0.11.2/EfiLib/legacy.c 2017-05-15 00:15:04.000000000 +0000 @@ -36,6 +36,7 @@ extern EFI_DEVICE_PATH EndDevicePath[]; extern EFI_GUID gEfiLegacyBiosProtocolGuid; EFI_GUID gEfiLegacyDevOrderVariableGuid = { 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 }}; +static EFI_GUID EfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }}; /** @@ -276,7 +277,7 @@ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", (UINTN) BootOrder[Index]); BootOptionVar = BdsLibGetVariableAndSize ( BootOption, - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, &BootOptionSize ); if (NULL == BootOptionVar) { @@ -462,7 +463,7 @@ Status = refit_call5_wrapper(gRT->SetVariable, BootString, - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, VAR_FLAG, BufferSize, Buffer @@ -747,7 +748,7 @@ BootOrder = BdsLibGetVariableAndSize ( L"BootOrder", - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, &BootOrderSize ); if (BootOrder == NULL) { @@ -817,13 +818,13 @@ if (BootOrderSize > 0) { Status = refit_call5_wrapper(gRT->SetVariable, L"BootOrder", - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, VAR_FLAG, BootOrderSize, BootOrder ); } else { - EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + EfiLibDeleteVariable (L"BootOrder", &EfiGlobalVariableGuid); } if (BootOrder != NULL) { @@ -861,7 +862,7 @@ Index2Del = 0; UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber); - Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid); + Status = EfiLibDeleteVariable (BootOption, &EfiGlobalVariableGuid); // // adjust boot order array @@ -940,7 +941,7 @@ BootOrder = BdsLibGetVariableAndSize ( L"BootOrder", - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, &BootOrderSize ); if (BootOrder == NULL) { @@ -952,14 +953,14 @@ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); BootOptionVar = BdsLibGetVariableAndSize ( BootOption, - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, &BootOptionSize ); if (NULL == BootOptionVar) { BootOptionSize = 0; Status = refit_call5_wrapper(gRT->GetVariable, BootOption, - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, NULL, &BootOptionSize, BootOptionVar @@ -1035,13 +1036,13 @@ if (BootOrderSize != 0) { Status = refit_call5_wrapper(gRT->SetVariable, L"BootOrder", - &gEfiGlobalVariableGuid, + &EfiGlobalVariableGuid, VAR_FLAG, BootOrderSize, BootOrder ); } else { - EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + EfiLibDeleteVariable (L"BootOrder", &EfiGlobalVariableGuid); } if (BootOrder != NULL) { diff -Nru refind-0.10.4/EfiLib/Platform.h refind-0.11.2/EfiLib/Platform.h --- refind-0.10.4/EfiLib/Platform.h 2015-12-02 23:18:05.000000000 +0000 +++ refind-0.11.2/EfiLib/Platform.h 2017-05-25 19:54:21.000000000 +0000 @@ -55,8 +55,8 @@ #include #include "../include/Bmp.h" -#include "efiConsoleControl.h" -#include "EfiLib/GenericBdsLib.h" +#include "../libeg/efiConsoleControl.h" +#include "../EfiLib/GenericBdsLib.h" #include "../refind/global.h" diff -Nru refind-0.10.4/filesystems/AutoGen.c refind-0.11.2/filesystems/AutoGen.c --- refind-0.10.4/filesystems/AutoGen.c 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/filesystems/AutoGen.c 2017-04-15 22:43:18.000000000 +0000 @@ -10,6 +10,7 @@ #include #include #include +#include "AutoGen.h" // Guids GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiFileInfoGuid = { 0x09576E92, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; diff -Nru refind-0.10.4/filesystems/btrfs.inf refind-0.11.2/filesystems/btrfs.inf --- refind-0.10.4/filesystems/btrfs.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/btrfs.inf 2017-05-28 13:54:08.000000000 +0000 @@ -0,0 +1,76 @@ +## @file +# +# btrfs.inf file to build rEFInd's Btrfs driver using the EDK2/UDK201# +# development kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = btrfs + FILE_GUID = 1388238d-a3f1-4f93-94c6-2fad8196e5d2 + MODULE_TYPE = UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = fsw_efi_main + FSTYPE = btrfs + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + fsw_efi.c + fsw_btrfs.c + fsw_core.c + fsw_efi.c + fsw_lib.c + fsw_efi_lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + MemoryAllocationLib + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + +[Ppis] + +[Protocols] + gEfiDiskIoProtocolGuid + gEfiBlockIoProtocolGuid + +[FeaturePcd] + +[Pcd] + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=btrfs + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=btrfs + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=btrfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=btrfs + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=btrfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=btrfs diff -Nru refind-0.10.4/filesystems/edk2/DriverBinding.h refind-0.11.2/filesystems/edk2/DriverBinding.h --- refind-0.10.4/filesystems/edk2/DriverBinding.h 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/filesystems/edk2/DriverBinding.h 2017-05-15 00:15:04.000000000 +0000 @@ -21,30 +21,32 @@ --*/ +/* + * rEFInd NOTE: This file is included only when compiling with GNU-EFI, + * which has not traditionally provided the definitions supplied here. + * Unfortunately, recent (ca. 3.0.5) versions of GNU-EFI have added + * SOME of these functions to an existing header file, creating problems + * when trying to maintain compatibility with multiple GNU-EFI versions. + * I've therefore renamed the relevant defines, types, and functions, + * both here and in fsw_efi.c; and included a define to match the only + * used name (REFIND_EFI_DRIVER_BINDING_PROTOCOL) to the traditional + * name (EFI_DRIVER_BINDING_PROTOCOL) in fsw_efi.c for compiling with + * TianoCore. + */ + #ifndef _EFI_DRIVER_BINDING_H_ #define _EFI_DRIVER_BINDING_H_ #include -// -// Global ID for the ControllerHandle Driver Protocol -// -#define EFI_DRIVER_BINDING_PROTOCOL_GUID \ +#define REFIND_EFI_DRIVER_BINDING_PROTOCOL_GUID \ { \ 0x18a031ab, 0xb443, 0x4d1a, {0xa5, 0xc0, 0xc, 0x9, 0x26, 0x1e, 0x9f, 0x71} \ } #define EFI_FORWARD_DECLARATION(x) typedef struct _##x x -EFI_FORWARD_DECLARATION (EFI_DRIVER_BINDING_PROTOCOL); - -/// -/// Device Path protocol. -/// -#define EFI_DEVICE_PATH_PROTOCOL_GUID \ - { \ - 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ - } +EFI_FORWARD_DECLARATION (REFIND_EFI_DRIVER_BINDING_PROTOCOL); // Begin included from DevicePath.h.... @@ -79,18 +81,19 @@ UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define ///< type of data. Size of data is included in Length. -} EFI_DEVICE_PATH_PROTOCOL; +} REFIND_EFI_DEVICE_PATH_PROTOCOL; #pragma pack() + // End included from DevicePath.h typedef EFI_STATUS (EFI_FUNCTION EFIAPI *EFI_DRIVER_BINDING_SUPPORTED) ( - IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN REFIND_EFI_DRIVER_BINDING_PROTOCOL * This, IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + IN REFIND_EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL ) /*++ @@ -114,9 +117,9 @@ typedef EFI_STATUS (EFI_FUNCTION EFIAPI *EFI_DRIVER_BINDING_START) ( - IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN REFIND_EFI_DRIVER_BINDING_PROTOCOL * This, IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + IN REFIND_EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL ) /*++ @@ -140,7 +143,7 @@ typedef EFI_STATUS (EFI_FUNCTION EFIAPI *EFI_DRIVER_BINDING_STOP) ( - IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN REFIND_EFI_DRIVER_BINDING_PROTOCOL * This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE * ChildHandleBuffer @@ -167,7 +170,7 @@ // // Interface structure for the ControllerHandle Driver Protocol // -struct _EFI_DRIVER_BINDING_PROTOCOL { +struct _REFIND_EFI_DRIVER_BINDING_PROTOCOL { EFI_DRIVER_BINDING_SUPPORTED Supported; EFI_DRIVER_BINDING_START Start; EFI_DRIVER_BINDING_STOP Stop; diff -Nru refind-0.10.4/filesystems/ext2.inf refind-0.11.2/filesystems/ext2.inf --- refind-0.10.4/filesystems/ext2.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/ext2.inf 2017-05-28 13:54:01.000000000 +0000 @@ -0,0 +1,73 @@ +## @file +# +# ext2.inf file to build rEFInd's ext2fs driver using the EDK2/UDK201# +# development kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ext2 + FILE_GUID = c1ad9a39-9e9c-4c5f-ac48-ddeb05408ad2 + MODULE_TYPE = UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = fsw_efi_main + FSTYPE = ext2 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + fsw_efi.c + fsw_ext2.c + fsw_core.c + fsw_lib.c + fsw_efi_lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + MemoryAllocationLib + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=ext2 + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=ext2 + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=ext2 + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=ext2 + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=ext2 + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=ext2 diff -Nru refind-0.10.4/filesystems/ext4.inf refind-0.11.2/filesystems/ext4.inf --- refind-0.10.4/filesystems/ext4.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/ext4.inf 2017-05-28 13:53:56.000000000 +0000 @@ -0,0 +1,74 @@ +## @file +# +# ext4.inf file to build rEFInd's ext4fs driver using the EDK2/UDK201# +# development kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ext4 + FILE_GUID = FD60D756-A4A9-4B87-BABF-E246DA740D4C + MODULE_TYPE = UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = fsw_efi_main + FSTYPE = ext4 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + fsw_efi.c + fsw_ext4.c + fsw_core.c + fsw_efi.c + fsw_lib.c + fsw_efi_lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + MemoryAllocationLib + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=ext4 + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=ext4 + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=ext4 + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=ext4 + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=ext4 + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=ext4 diff -Nru refind-0.10.4/filesystems/fsw_core.c refind-0.11.2/filesystems/fsw_core.c --- refind-0.10.4/filesystems/fsw_core.c 2015-12-02 18:30:48.000000000 +0000 +++ refind-0.11.2/filesystems/fsw_core.c 2017-04-15 22:26:36.000000000 +0000 @@ -38,6 +38,7 @@ */ #include "fsw_core.h" +#include "fsw_efi.h" // functions @@ -46,7 +47,6 @@ #define MAX_CACHE_LEVEL (5) - /** * Mount a volume with a given file system driver. This function is called by the * host driver to make a volume accessible. The file system driver to use is specified @@ -314,6 +314,7 @@ vol->bcache = NULL; } vol->bcache_size = 0; + fsw_efi_clear_cache(); } /** diff -Nru refind-0.10.4/filesystems/fsw_efi.c refind-0.11.2/filesystems/fsw_efi.c --- refind-0.10.4/filesystems/fsw_efi.c 2016-10-09 23:09:30.000000000 +0000 +++ refind-0.11.2/filesystems/fsw_efi.c 2017-10-22 20:35:29.000000000 +0000 @@ -43,10 +43,20 @@ #ifdef __MAKEWITH_GNUEFI #include "edk2/DriverBinding.h" #include "edk2/ComponentName.h" +#define gMyEfiSimpleFileSystemProtocolGuid FileSystemProtocol #else +#define REFIND_EFI_DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING_PROTOCOL #define REFIND_EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL +#define REFIND_EFI_COMPONENT_NAME_PROTOCOL_GUID EFI_COMPONENT_NAME_PROTOCOL_GUID +#define REFIND_EFI_DRIVER_BINDING_PROTOCOL_GUID EFI_DRIVER_BINDING_PROTOCOL_GUID +#define REFIND_EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL +#define EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID \ + { 0xDB47D7D3,0xFE81, 0x11d3, {0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } +#define gMyEfiSimpleFileSystemProtocolGuid gEfiSimpleFileSystemProtocolGuid #endif + #include "../include/refit_call_wrapper.h" +#include "../include/version.h" #define DEBUG_LEVEL 0 @@ -55,54 +65,40 @@ #define FSTYPE ext2 #endif -#ifdef __MAKEWITH_GNUEFI - -#define EFI_DISK_IO_PROTOCOL_GUID \ - { \ - 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ - } - -#define EFI_BLOCK_IO_PROTOCOL_GUID \ - { \ - 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ - } - -EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID; -EFI_GUID gEfiComponentNameProtocolGuid = REFIND_EFI_COMPONENT_NAME_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; -#define gEfiSimpleFileSystemProtocolGuid FileSystemProtocol -#endif +EFI_GUID gMyEfiDriverBindingProtocolGuid = REFIND_EFI_DRIVER_BINDING_PROTOCOL_GUID; +EFI_GUID gMyEfiComponentNameProtocolGuid = REFIND_EFI_COMPONENT_NAME_PROTOCOL_GUID; +EFI_GUID gMyEfiDiskIoProtocolGuid = REFIND_EFI_DISK_IO_PROTOCOL_GUID; +EFI_GUID gMyEfiBlockIoProtocolGuid = REFIND_EFI_BLOCK_IO_PROTOCOL_GUID; +EFI_GUID gMyEfiFileInfoGuid = EFI_FILE_INFO_ID; +EFI_GUID gMyEfiFileSystemInfoGuid = EFI_FILE_SYSTEM_INFO_ID; +EFI_GUID gMyEfiFileSystemVolumeLabelInfoIdGuid = EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID; /** 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.10.4 " FSW_EFI_STRINGIFY(t) L" File System Driver" +#define FSW_EFI_DRIVER_NAME(t) L"rEFInd 0.11.2 " FSW_EFI_STRINGIFY(t) L" File System Driver" // function prototypes -EFI_STATUS EFIAPI fsw_efi_DriverBinding_Supported(IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath); -EFI_STATUS EFIAPI fsw_efi_DriverBinding_Start(IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath); -EFI_STATUS EFIAPI fsw_efi_DriverBinding_Stop(IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer); +EFI_STATUS EFIAPI fsw_efi_DriverBinding_Supported(IN REFIND_EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN REFIND_EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath); +EFI_STATUS EFIAPI fsw_efi_DriverBinding_Start(IN REFIND_EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN REFIND_EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath); +EFI_STATUS EFIAPI fsw_efi_DriverBinding_Stop(IN REFIND_EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer); EFI_STATUS EFIAPI fsw_efi_ComponentName_GetDriverName(IN REFIND_EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName); -EFI_STATUS EFIAPI fsw_efi_ComponentName_GetControllerName(IN REFIND_EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName); + IN CHAR8 *Language, + OUT CHAR16 **DriverName); +EFI_STATUS EFIAPI fsw_efi_ComponentName_GetControllerName(IN REFIND_EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName); void EFIAPI fsw_efi_change_blocksize(struct fsw_volume *vol, fsw_u32 old_phys_blocksize, fsw_u32 old_log_blocksize, @@ -164,7 +160,7 @@ * Interface structure for the EFI Driver Binding protocol. */ -EFI_DRIVER_BINDING_PROTOCOL fsw_efi_DriverBinding_table = { +REFIND_EFI_DRIVER_BINDING_PROTOCOL fsw_efi_DriverBinding_table = { fsw_efi_DriverBinding_Supported, fsw_efi_DriverBinding_Start, fsw_efi_DriverBinding_Stop, @@ -197,7 +193,7 @@ extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(FSTYPE); -static VOID EFIAPI fsw_efi_clear_cache(VOID) { +VOID EFIAPI fsw_efi_clear_cache(VOID) { int i; // clear the cache @@ -233,7 +229,7 @@ fsw_efi_DriverBinding_table.DriverBindingHandle = ImageHandle; // install Driver Binding protocol Status = refit_call4_wrapper(BS->InstallProtocolInterface, &fsw_efi_DriverBinding_table.DriverBindingHandle, - &gEfiDriverBindingProtocolGuid, + &gMyEfiDriverBindingProtocolGuid, EFI_NATIVE_INTERFACE, &fsw_efi_DriverBinding_table); if (EFI_ERROR (Status)) { @@ -242,7 +238,7 @@ // install Component Name protocol Status = refit_call4_wrapper(BS->InstallProtocolInterface, &fsw_efi_DriverBinding_table.DriverBindingHandle, - &gEfiComponentNameProtocolGuid, + &gMyEfiComponentNameProtocolGuid, EFI_NATIVE_INTERFACE, &fsw_efi_ComponentName_table); if (EFI_ERROR (Status)) { @@ -272,9 +268,9 @@ * and implicitly checks if the disk is already in use by another driver. */ -EFI_STATUS EFIAPI fsw_efi_DriverBinding_Supported(IN EFI_DRIVER_BINDING_PROTOCOL *This, +EFI_STATUS EFIAPI fsw_efi_DriverBinding_Supported(IN REFIND_EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath) + IN REFIND_EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath) { EFI_STATUS Status; EFI_DISK_IO *DiskIo; @@ -283,7 +279,7 @@ // first, open DiskIO Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle, - &gEfiDiskIoProtocolGuid, + &gMyEfiDiskIoProtocolGuid, (VOID **) &DiskIo, This->DriverBindingHandle, ControllerHandle, @@ -293,13 +289,13 @@ // we were just checking, close it again refit_call4_wrapper(BS->CloseProtocol, ControllerHandle, - &gEfiDiskIoProtocolGuid, + &gMyEfiDiskIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); // next, check BlockIO without actually opening it Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle, - &gEfiBlockIoProtocolGuid, + &gMyEfiBlockIoProtocolGuid, NULL, This->DriverBindingHandle, ControllerHandle, @@ -320,9 +316,9 @@ * device handle. */ -EFI_STATUS EFIAPI fsw_efi_DriverBinding_Start(IN EFI_DRIVER_BINDING_PROTOCOL *This, +EFI_STATUS EFIAPI fsw_efi_DriverBinding_Start(IN REFIND_EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath) + IN REFIND_EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath) { EFI_STATUS Status; EFI_BLOCK_IO *BlockIo; @@ -335,7 +331,7 @@ // open consumed protocols Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle, - &gEfiBlockIoProtocolGuid, + &gMyEfiBlockIoProtocolGuid, (VOID **) &BlockIo, This->DriverBindingHandle, ControllerHandle, @@ -346,7 +342,7 @@ } Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle, - &gEfiDiskIoProtocolGuid, + &gMyEfiDiskIoProtocolGuid, (VOID **) &DiskIo, This->DriverBindingHandle, ControllerHandle, @@ -368,13 +364,12 @@ Status = fsw_efi_map_status(fsw_mount(Volume, &fsw_efi_host_table, &FSW_FSTYPE_TABLE_NAME(FSTYPE), &Volume->vol), Volume); - if (!EFI_ERROR(Status)) { // register the SimpleFileSystem protocol Volume->FileSystem.Revision = EFI_FILE_IO_INTERFACE_REVISION; Volume->FileSystem.OpenVolume = fsw_efi_FileSystem_OpenVolume; Status = refit_call4_wrapper(BS->InstallMultipleProtocolInterfaces, &ControllerHandle, - &gEfiSimpleFileSystemProtocolGuid, + &gMyEfiSimpleFileSystemProtocolGuid, &Volume->FileSystem, NULL); if (EFI_ERROR(Status)) { @@ -389,7 +384,7 @@ FreePool(Volume); refit_call4_wrapper(BS->CloseProtocol, ControllerHandle, - &gEfiDiskIoProtocolGuid, + &gMyEfiDiskIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); } @@ -406,7 +401,7 @@ * case; it closes all file handles between commands. */ -EFI_STATUS EFIAPI fsw_efi_DriverBinding_Stop(IN EFI_DRIVER_BINDING_PROTOCOL *This, +EFI_STATUS EFIAPI fsw_efi_DriverBinding_Stop(IN REFIND_EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer) @@ -421,7 +416,7 @@ // get the installed SimpleFileSystem interface Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle, - &gEfiSimpleFileSystemProtocolGuid, + &gMyEfiSimpleFileSystemProtocolGuid, (VOID **) &FileSystem, This->DriverBindingHandle, ControllerHandle, @@ -434,7 +429,7 @@ // uninstall Simple File System protocol Status = refit_call4_wrapper(BS->UninstallMultipleProtocolInterfaces, ControllerHandle, - &gEfiSimpleFileSystemProtocolGuid, &Volume->FileSystem, + &gMyEfiSimpleFileSystemProtocolGuid, &Volume->FileSystem, NULL); if (EFI_ERROR(Status)) { // Print(L"Fsw ERROR: UninstallMultipleProtocolInterfaces returned %x\n", Status); @@ -451,7 +446,7 @@ // close the consumed protocols Status = refit_call4_wrapper(BS->CloseProtocol, ControllerHandle, - &gEfiDiskIoProtocolGuid, + &gMyEfiDiskIoProtocolGuid, This->DriverBindingHandle, ControllerHandle); @@ -1028,14 +1023,14 @@ struct fsw_volume_stat vsb; - if (CompareGuid(InformationType, &gEfiFileInfoGuid)) { + if (CompareGuid(InformationType, &gMyEfiFileInfoGuid)) { #if DEBUG_LEVEL Print(L"fsw_efi_dnode_getinfo: FILE_INFO\n"); #endif Status = fsw_efi_dnode_fill_FileInfo(Volume, File->shand.dnode, BufferSize, Buffer); - } else if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid)) { + } else if (CompareGuid(InformationType, &gMyEfiFileSystemInfoGuid)) { #if DEBUG_LEVEL Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_INFO\n"); #endif @@ -1066,7 +1061,7 @@ *BufferSize = RequiredSize; Status = EFI_SUCCESS; - } else if (CompareGuid(InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + } else if (CompareGuid(InformationType, &gMyEfiFileSystemVolumeLabelInfoIdGuid)) { #if DEBUG_LEVEL Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_VOLUME_LABEL\n"); #endif diff -Nru refind-0.10.4/filesystems/fsw_efi.h refind-0.11.2/filesystems/fsw_efi.h --- refind-0.10.4/filesystems/fsw_efi.h 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/filesystems/fsw_efi.h 2017-05-15 00:15:04.000000000 +0000 @@ -44,6 +44,16 @@ #define CompareGuid(a, b) CompareGuid(a, b)==0 #endif +#define REFIND_EFI_DISK_IO_PROTOCOL_GUID \ + { \ + 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +#define REFIND_EFI_BLOCK_IO_PROTOCOL_GUID \ + { \ + 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + /** * EFI Host: Private per-volume structure. */ @@ -100,6 +110,6 @@ UINTN fsw_efi_strsize(struct fsw_string *s); VOID fsw_efi_strcpy(CHAR16 *Dest, struct fsw_string *src); - +VOID EFIAPI fsw_efi_clear_cache(VOID); #endif diff -Nru refind-0.10.4/filesystems/fsw_efi_lib.c refind-0.11.2/filesystems/fsw_efi_lib.c --- refind-0.10.4/filesystems/fsw_efi_lib.c 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/filesystems/fsw_efi_lib.c 2017-04-15 13:43:05.000000000 +0000 @@ -115,7 +115,7 @@ VOID fsw_efi_strcpy(CHAR16 *Dest, struct fsw_string *src) { - if (src->type == FSW_STRING_TYPE_EMPTY | src->size == 0) { + if ((src->type == FSW_STRING_TYPE_EMPTY) | (src->size == 0)) { Dest[0] = 0; } else if (src->type == FSW_STRING_TYPE_UTF16) { CopyMem(Dest, src->data, src->size); diff -Nru refind-0.10.4/filesystems/fsw_iso9660.c refind-0.11.2/filesystems/fsw_iso9660.c --- refind-0.10.4/filesystems/fsw_iso9660.c 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/filesystems/fsw_iso9660.c 2017-08-29 13:05:14.000000000 +0000 @@ -220,7 +220,7 @@ str->data = tmp; str->len += len; - if ((nm->flags & RR_NM_CONT) == 0); + if ((nm->flags & RR_NM_CONT) == 0) goto done; } } diff -Nru refind-0.10.4/filesystems/hfs.inf refind-0.11.2/filesystems/hfs.inf --- refind-0.10.4/filesystems/hfs.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/hfs.inf 2017-05-28 13:53:49.000000000 +0000 @@ -0,0 +1,74 @@ +## @file +# +# hfs.inf file to build rEFInd's HFS+ driver using the EDK2/UDK201# +# development kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = hfs + FILE_GUID = cc9ec9b9-d3e0-418e-bfa2-b8148f11ffb8 + MODULE_TYPE = UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = fsw_efi_main + FSTYPE = hfs + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + fsw_efi.c + fsw_hfs.c + fsw_core.c + fsw_efi.c + fsw_lib.c + fsw_efi_lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + MemoryAllocationLib + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=hfs + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=hfs + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=hfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=hfs + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=hfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=hfs diff -Nru refind-0.10.4/filesystems/iso9660.inf refind-0.11.2/filesystems/iso9660.inf --- refind-0.10.4/filesystems/iso9660.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/iso9660.inf 2017-05-28 13:53:43.000000000 +0000 @@ -0,0 +1,74 @@ +## @file +# +# iso9660.inf file to build rEFInd's ISO-9660 driver using the EDK2/UDK201# +# development kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = iso9660 + FILE_GUID = ff0c069a-8544-4535-b3c7-61fa106ab88d + MODULE_TYPE = UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = fsw_efi_main + FSTYPE = iso9660 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + fsw_efi.c + fsw_iso9660.c + fsw_core.c + fsw_efi.c + fsw_lib.c + fsw_efi_lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + MemoryAllocationLib + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=iso9660 + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=iso9660 + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=iso9660 + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=iso9660 + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=iso9660 + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=iso9660 diff -Nru refind-0.10.4/filesystems/Make.tiano refind-0.11.2/filesystems/Make.tiano --- refind-0.10.4/filesystems/Make.tiano 2015-12-06 21:20:15.000000000 +0000 +++ refind-0.11.2/filesystems/Make.tiano 2017-07-30 19:04:35.000000000 +0000 @@ -1,5 +1,5 @@ # -# filesystems/Make.common +# filesystems/Make.tiano # Build control file for rEFInd's EFI filesystem drivers # @@ -11,9 +11,9 @@ include ../Make.common # Below file defines TARGET (RELEASE or DEBUG) and TOOL_CHAIN_TAG (GCC44, GCC45, or GCC46) -#include $(EDK2BASE)/Conf/target.txt +#include $(TIANOBASE)/Conf/target.txt -EFILIB = $(EDK2BASE)/Build/Mde/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH)/MdePkg/Library +EFILIB = $(TIANOBASE)/Build/Mde/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH)/MdePkg/Library ALL_EFILIBS = $(EFILIB)/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib/OUTPUT/BaseDebugPrintErrorLevelLib.lib \ $(EFILIB)/BasePrintLib/BasePrintLib/OUTPUT/BasePrintLib.lib \ $(EFILIB)/BasePcdLibNull/BasePcdLibNull/OUTPUT/BasePcdLibNull.lib \ @@ -31,11 +31,11 @@ ALL_EFILIBS += $(EFILIB)/BaseStackCheckLib/BaseStackCheckLib/OUTPUT/BaseStackCheckLib.lib endif -TIANO_INCLUDE_DIRS = -I $(EDK2BASE)/MdePkg \ - -I $(EDK2BASE)/MdePkg/Include \ - -I $(EDK2BASE)/MdePkg/Include/$(ARCHDIR) \ - -I $(EDK2BASE)/EdkCompatibilityPkg/Foundation/Framework/Include \ - -I $(EDK2BASE)/EdkCompatibilityPkg/Foundation/Library/Dxe/Include +TIANO_INCLUDE_DIRS = -I $(TIANOBASE)/MdePkg \ + -I $(TIANOBASE)/MdePkg/Include \ + -I $(TIANOBASE)/MdePkg/Include/$(ARCHDIR) \ + -I $(TIANOBASE)/EdkCompatibilityPkg/Foundation/Framework/Include \ + -I $(TIANOBASE)/EdkCompatibilityPkg/Foundation/Library/Dxe/Include FSW_NAMES = fsw_efi fsw_core fsw_efi_lib fsw_lib AutoGen OBJS = $(FSW_NAMES:=.obj) diff -Nru refind-0.10.4/filesystems/ntfs.inf refind-0.11.2/filesystems/ntfs.inf --- refind-0.10.4/filesystems/ntfs.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/ntfs.inf 2017-05-28 13:53:37.000000000 +0000 @@ -0,0 +1,74 @@ +## @file +# +# ntfs.inf file to build rEFInd's NTFS driver using the EDK2/UDK201# +# development kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ntfs + FILE_GUID = a916a90d-fb2c-4797-82cd-415c8802999f + MODULE_TYPE = UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = fsw_efi_main + FSTYPE = ntfs + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + fsw_efi.c + fsw_ntfs.c + fsw_core.c + fsw_efi.c + fsw_lib.c + fsw_efi_lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + MemoryAllocationLib + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=ntfs + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=ntfs + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=ntfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=ntfs + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=ntfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=ntfs diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDisk.asl refind-0.11.2/filesystems/RamDiskDxe/RamDisk.asl --- refind-0.10.4/filesystems/RamDiskDxe/RamDisk.asl 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDisk.asl 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,44 @@ +/** @file + The definition block in ACPI table for NVDIMM root device. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
        +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +DefinitionBlock ( + "RamDisk.aml", + "SSDT", + 2, + "INTEL ", + "RamDisk ", + 0x1000 + ) +{ + Scope (\_SB) + { + Device (NVDR) + { + // + // Define _HID, "ACPI0012" NVDIMM Root Device + // + Name (_HID, "ACPI0012") + + // + // Readable name of this device + // + Name (_STR, Unicode ("NVDIMM Root Device")) + + Method (_STA, 0) + { + Return (0x0f) + } + } + } +} diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskBlockIo.c refind-0.11.2/filesystems/RamDiskDxe/RamDiskBlockIo.c --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskBlockIo.c 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskBlockIo.c 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,485 @@ +/** @file + Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "RamDiskImpl.h" + +// +// The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle +// for newly registered RAM disks +// +EFI_BLOCK_IO_PROTOCOL mRamDiskBlockIoTemplate = { + EFI_BLOCK_IO_PROTOCOL_REVISION, + (EFI_BLOCK_IO_MEDIA *) 0, + RamDiskBlkIoReset, + RamDiskBlkIoReadBlocks, + RamDiskBlkIoWriteBlocks, + RamDiskBlkIoFlushBlocks +}; + +// +// The EFI_BLOCK_IO_PROTOCOL2 instances that is installed onto the handle +// for newly registered RAM disks +// +EFI_BLOCK_IO2_PROTOCOL mRamDiskBlockIo2Template = { + (EFI_BLOCK_IO_MEDIA *) 0, + RamDiskBlkIo2Reset, + RamDiskBlkIo2ReadBlocksEx, + RamDiskBlkIo2WriteBlocksEx, + RamDiskBlkIo2FlushBlocksEx +}; + + +/** + Initialize the BlockIO & BlockIO2 protocol of a RAM disk device. + + @param[in] PrivateData Points to RAM disk private data. + +**/ +VOID +RamDiskInitBlockIo ( + IN RAM_DISK_PRIVATE_DATA *PrivateData + ) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO2_PROTOCOL *BlockIo2; + EFI_BLOCK_IO_MEDIA *Media; + + BlockIo = &PrivateData->BlockIo; + BlockIo2 = &PrivateData->BlockIo2; + Media = &PrivateData->Media; + + CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL)); + CopyMem (BlockIo2, &mRamDiskBlockIo2Template, sizeof (EFI_BLOCK_IO2_PROTOCOL)); + + BlockIo->Media = Media; + BlockIo2->Media = Media; + Media->RemovableMedia = FALSE; + Media->MediaPresent = TRUE; + Media->LogicalPartition = FALSE; + Media->ReadOnly = FALSE; + Media->WriteCaching = FALSE; + Media->BlockSize = RAM_DISK_BLOCK_SIZE; + Media->LastBlock = DivU64x32 ( + PrivateData->Size + RAM_DISK_BLOCK_SIZE - 1, + RAM_DISK_BLOCK_SIZE + ) - 1; +} + + +/** + Reset the Block Device. + + @param This Indicates a pointer to the calling context. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return EFI_SUCCESS; +} + + +/** + Read BufferSize bytes from Lba into Buffer. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId Id of the media, changes every time the media is + replaced. + @param[in] Lba The starting Logical Block Address to read from. + @param[in] BufferSize Size of Buffer, must be a multiple of device block + size. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for either having + implicit or explicit ownership of the buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing + the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId does not matched the current + device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block + size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + RAM_DISK_PRIVATE_DATA *PrivateData; + UINTN NumberOfBlocks; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This); + + if (MediaId != PrivateData->Media.MediaId) { + return EFI_MEDIA_CHANGED; + } + + if ((BufferSize % PrivateData->Media.BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize; + if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + CopyMem ( + Buffer, + (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)), + BufferSize + ); + + return EFI_SUCCESS; +} + + +/** + Write BufferSize bytes from Lba into Buffer. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the write request is for. + @param[in] Lba The starting logical block address to be written. + The caller is responsible for writing to only + legitimate locations. + @param[in] BufferSize Size of Buffer, must be a multiple of device block + size. + @param[in] Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing + the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current + device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block + size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not + valid, or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + RAM_DISK_PRIVATE_DATA *PrivateData; + UINTN NumberOfBlocks; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This); + + if (MediaId != PrivateData->Media.MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (TRUE == PrivateData->Media.ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + if ((BufferSize % PrivateData->Media.BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize; + if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + CopyMem ( + (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)), + Buffer, + BufferSize + ); + + return EFI_SUCCESS; +} + + +/** + Flush the Block Device. + + @param[in] This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding data was written to the device. + @retval EFI_DEVICE_ERROR The device reported an error while writting + back the data + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +/** + Resets the block device hardware. + + @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL. + @param[in] ExtendedVerification The flag about if extend verificate. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The block device is not functioning correctly + and could not be reset. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2Reset ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return EFI_SUCCESS; +} + + +/** + Reads the requested number of blocks from the device. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the read request is for. + @param[in] Lba The starting logical block address to read + from on the device. + @param[in, out] Token A pointer to the token associated with the + transaction. + @param[in] BufferSize The size of the Buffer in bytes. This must be + a multiple of the intrinsic block size of the + device. + @param[out] Buffer A pointer to the destination buffer for the + data. The caller is responsible for either + having implicit or explicit ownership of the + buffer. + + @retval EFI_SUCCESS The read request was queued if Token->Event + is not NULL. The data was read correctly from + the device if the Token->Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not on proper + alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2ReadBlocksEx ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + RAM_DISK_PRIVATE_DATA *PrivateData; + EFI_STATUS Status; + + PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This); + + Status = RamDiskBlkIoReadBlocks ( + &PrivateData->BlockIo, + MediaId, + Lba, + BufferSize, + Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If caller's event is given, signal it after the memory read completes. + // + if ((Token != NULL) && (Token->Event != NULL)) { + Token->TransactionStatus = EFI_SUCCESS; + gBS->SignalEvent (Token->Event); + } + + return EFI_SUCCESS; +} + + +/** + Writes a specified number of blocks to the device. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the write request is for. + @param[in] Lba The starting logical block address to be + written. The caller is responsible for + writing to only legitimate locations. + @param[in, out] Token A pointer to the token associated with the + transaction. + @param[in] BufferSize The size in bytes of Buffer. This must be a + multiple of the intrinsic block size of the + device. + @param[in] Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The write request was queued if Event is not + NULL. The data was written correctly to the + device if the Event is NULL. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the write operation. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not + valid, or the buffer is not on proper + alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2WriteBlocksEx ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + RAM_DISK_PRIVATE_DATA *PrivateData; + EFI_STATUS Status; + + PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This); + + Status = RamDiskBlkIoWriteBlocks ( + &PrivateData->BlockIo, + MediaId, + Lba, + BufferSize, + Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If caller's event is given, signal it after the memory write completes. + // + if ((Token != NULL) && (Token->Event != NULL)) { + Token->TransactionStatus = EFI_SUCCESS; + gBS->SignalEvent (Token->Event); + } + + return EFI_SUCCESS; +} + + +/** + Flushes all modified data to a physical block device. + + @param[in] This Indicates a pointer to the calling context. + @param[in, out] Token A pointer to the token associated with the + transaction. + + @retval EFI_SUCCESS The flush request was queued if Event is not + NULL. All outstanding data was written + correctly to the device if the Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to write data. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2FlushBlocksEx ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN OUT EFI_BLOCK_IO2_TOKEN *Token + ) +{ + RAM_DISK_PRIVATE_DATA *PrivateData; + + PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This); + + if (TRUE == PrivateData->Media.ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + // + // If caller's event is given, signal it directly. + // + if ((Token != NULL) && (Token->Event != NULL)) { + Token->TransactionStatus = EFI_SUCCESS; + gBS->SignalEvent (Token->Event); + } + + return EFI_SUCCESS; +} diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskDriver.c refind-0.11.2/filesystems/RamDiskDxe/RamDiskDriver.c --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskDriver.c 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskDriver.c 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,249 @@ +/** @file + The driver entry point for RamDiskDxe driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "RamDiskImpl.h" + +// +// Handle for the EFI_RAM_DISK_PROTOCOL instance +// +EFI_HANDLE mRamDiskHandle = NULL; + +// +// The EFI_RAM_DISK_PROTOCOL instances that is installed onto the driver +// handle +// +EFI_RAM_DISK_PROTOCOL mRamDiskProtocol = { + RamDiskRegister, + RamDiskUnregister +}; + +// +// RamDiskDxe driver maintains a list of registered RAM disks. +// +LIST_ENTRY RegisteredRamDisks; + +// +// Pointers to the EFI_ACPI_TABLE_PROTOCOL and EFI_ACPI_SDT_PROTOCOL. +// +EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol = NULL; +EFI_ACPI_SDT_PROTOCOL *mAcpiSdtProtocol = NULL; + + +/** + Check whether EFI_ACPI_TABLE_PROTOCOL and EFI_ACPI_SDT_PROTOCOL are produced. + If both protocols are produced, publish all the reserved memory type RAM + disks to the NVDIMM Firmware Interface Table (NFIT). + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context The pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +RamDiskAcpiCheck ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Entry; + RAM_DISK_PRIVATE_DATA *PrivateData; + + gBS->CloseEvent (Event); + + // + // Locate the EFI_ACPI_TABLE_PROTOCOL. + // + Status = gBS->LocateProtocol ( + &gEfiAcpiTableProtocolGuid, + NULL, + (VOID **)&mAcpiTableProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_INFO, + "RamDiskAcpiCheck: Cannot locate the EFI ACPI Table Protocol, " + "unable to publish RAM disks to NFIT.\n" + )); + return; + } + + // + // Locate the EFI_ACPI_SDT_PROTOCOL. + // + Status = gBS->LocateProtocol ( + &gEfiAcpiSdtProtocolGuid, + NULL, + (VOID **)&mAcpiSdtProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_INFO, + "RamDiskAcpiCheck: Cannot locate the EFI ACPI Sdt Protocol, " + "unable to publish RAM disks to NFIT.\n" + )); + mAcpiTableProtocol = NULL; + return; + } + + EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) { + PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry); + RamDiskPublishNfit (PrivateData); + } +} + + +/** + The entry point for RamDiskDxe driver. + + @param[in] ImageHandle The image handle of the driver. + @param[in] SystemTable The system table. + + @retval EFI_ALREADY_STARTED The driver already exists in system. + @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of + resources. + @retval EFI_SUCCES All the related protocols are installed on + the driver. + +**/ +EFI_STATUS +EFIAPI +RamDiskDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate; + VOID *DummyInterface; + EFI_EVENT Event; + + // + // If already started, return. + // + Status = gBS->LocateProtocol ( + &gEfiRamDiskProtocolGuid, + NULL, + &DummyInterface + ); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Driver already started!\n")); + return EFI_ALREADY_STARTED; + } + + // + // Create a private data structure. + // + ConfigPrivate = AllocateCopyPool (sizeof (RAM_DISK_CONFIG_PRIVATE_DATA), &mRamDiskConfigPrivateDataTemplate); + if (ConfigPrivate == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Install RAM disk configuration form + // + Status = InstallRamDiskConfigForm (ConfigPrivate); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // + // Install the EFI_RAM_DISK_PROTOCOL and RAM disk private data onto a + // new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mRamDiskHandle, + &gEfiRamDiskProtocolGuid, + &mRamDiskProtocol, + &gEfiCallerIdGuid, + ConfigPrivate, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // + // Initialize the list of registered RAM disks maintained by the driver + // + InitializeListHead (&RegisteredRamDisks); + + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + RamDiskAcpiCheck, + NULL, + &Event + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; + +ErrorExit: + if (ConfigPrivate != NULL) { + UninstallRamDiskConfigForm (ConfigPrivate); + } + + return Status; +} + + +/** + Unload the RamDiskDxe driver and its configuration form. + + @param[in] ImageHandle The driver's image handle. + + @retval EFI_SUCCESS The RamDiskDxe driver and its configuration + form is unloaded. + @retval Others Failed to unload the form. + +**/ +EFI_STATUS +EFIAPI +RamDiskDxeUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate; + + Status = gBS->HandleProtocol ( + mRamDiskHandle, + &gEfiCallerIdGuid, + (VOID **) &ConfigPrivate + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (ConfigPrivate->Signature == RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE); + + // + // Unregister all registered RAM disks + // + UnregisterAllRamDisks (); + + gBS->UninstallMultipleProtocolInterfaces ( + mRamDiskHandle, + &gEfiRamDiskProtocolGuid, + &mRamDiskProtocol, + &gEfiCallerIdGuid, + ConfigPrivate, + NULL + ); + + UninstallRamDiskConfigForm (ConfigPrivate); + + return EFI_SUCCESS; +} diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskDxe.inf refind-0.11.2/filesystems/RamDiskDxe/RamDiskDxe.inf --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskDxe.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskDxe.inf 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,91 @@ +## @file +# Produces EFI_RAM_DISK_PROTOCOL and provides the capability to +# create/remove RAM disks in a setup browser. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
        +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = RamDiskDxe + MODULE_UNI_FILE = RamDiskDxe.uni + FILE_GUID = 28A03FF4-12B3-4305-A417-BB1A4F94081E + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = RamDiskDxeEntryPoint + UNLOAD_IMAGE = RamDiskDxeUnload + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + RamDiskDriver.c + RamDiskImpl.c + RamDiskBlockIo.c + RamDiskProtocol.c + RamDiskFileExplorer.c + RamDiskImpl.h + RamDiskHii.vfr + RamDiskHiiStrings.uni + RamDiskNVData.h + RamDisk.asl + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + UefiLib + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiHiiServicesLib + MemoryAllocationLib + HiiLib + FileExplorerLib + DevicePathLib + PrintLib + PcdLib + DxeServicesLib + +[Guids] + gEfiIfrTianoGuid ## PRODUCES ## GUID # HII opcode + ## PRODUCES ## HII + ## CONSUMES ## HII + gRamDiskFormSetGuid + gEfiVirtualDiskGuid ## SOMETIMES_CONSUMES ## GUID + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID # Indicate the information type + +[Protocols] + gEfiRamDiskProtocolGuid ## PRODUCES + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEfiDevicePathProtocolGuid ## PRODUCES + gEfiBlockIoProtocolGuid ## PRODUCES + gEfiBlockIo2ProtocolGuid ## PRODUCES + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + gEfiAcpiTableProtocolGuid ## SOMETIMES_CONSUMES + gEfiAcpiSdtProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## SOMETIMES_CONSUMES + +[Depex] + gEfiHiiConfigRoutingProtocolGuid AND + gEfiHiiDatabaseProtocolGuid diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskDxe.uni refind-0.11.2/filesystems/RamDiskDxe/RamDiskDxe.uni --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskDxe.uni 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskDxe.uni 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,20 @@ +// /** @file +// Produces EFI_RAM_DISK_PROTOCOL and provides the capability to +// create/remove RAM disks in a setup browser. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
        +// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Produces EFI_RAM_DISK_PROTOCOL and provides the capability to create/remove RAM disks in a setup browser." + +#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI_RAM_DISK_PROTOCOL and provides the capability to create/remove RAM disks in a setup browser." + diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskFileExplorer.c refind-0.11.2/filesystems/RamDiskDxe/RamDiskFileExplorer.c --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskFileExplorer.c 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskFileExplorer.c 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,253 @@ +/** @file + Internal file explorer helper functions for RamDiskDxe driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "RamDiskImpl.h" + + +/** + Helper function called as part of the code needed to allocate the proper + sized buffer for various EFI interfaces. + + @param[in, out] Status Current status. + @param[in, out] Buffer Current allocated buffer, or NULL. + @param[in] BufferSize Current buffer size needed. + + @retval TRUE If the buffer was reallocated and the caller should + try the API again. + @retval FALSE The caller should not call this function again. + +**/ +BOOLEAN +GrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +{ + BOOLEAN TryAgain; + + // + // If this is an initial request, buffer will be null with a new buffer size + // + if ((*Buffer == NULL) && (BufferSize != 0)) { + *Status = EFI_BUFFER_TOO_SMALL; + } + // + // If the status code is "buffer too small", resize the buffer + // + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + if (*Buffer != NULL) { + FreePool (*Buffer); + } + + *Buffer = AllocateZeroPool (BufferSize); + + if (*Buffer != NULL) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + // + // If there's an error, free the buffer + // + if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { + FreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + + +/** + This function gets the file information from an open file descriptor, + and stores it in a buffer allocated from pool. + + @param[in] FHand File Handle. + + @return A pointer to a buffer with file information or NULL is returned. + +**/ +EFI_FILE_INFO * +FileInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileInfoGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + + +/** + This function will open a file or directory referenced by DevicePath. + + This function opens a file with the open mode according to the file path. The + Attributes is valid only for EFI_FILE_MODE_CREATE. + + @param[in, out] FilePath On input, the device path to the file. + On output, the remaining device path. + @param[out] FileHandle Pointer to the file handle. + @param[in] OpenMode The mode to open the file with. + @param[in] Attributes The file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or + the medium is no longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open + the file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +OpenFileByDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT EFI_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol; + EFI_FILE_PROTOCOL *Handle1; + EFI_FILE_PROTOCOL *Handle2; + EFI_HANDLE DeviceHandle; + + if ((FilePath == NULL || FileHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + FilePath, + &DeviceHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**)&EfiSimpleFileSystemProtocol, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1); + if (EFI_ERROR (Status)) { + FileHandle = NULL; + return Status; + } + + // + // go down directories one node at a time. + // + while (!IsDevicePathEnd (*FilePath)) { + // + // For file system access each node should be a file path component + // + if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || + DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP + ) { + FileHandle = NULL; + return (EFI_INVALID_PARAMETER); + } + // + // Open this file path node + // + Handle2 = Handle1; + Handle1 = NULL; + + // + // Try to test opening an existing file + // + Status = Handle2->Open ( + Handle2, + &Handle1, + ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, + OpenMode &~EFI_FILE_MODE_CREATE, + 0 + ); + + // + // see if the error was that it needs to be created + // + if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) { + Status = Handle2->Open ( + Handle2, + &Handle1, + ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, + OpenMode, + Attributes + ); + } + // + // Close the last node + // + Handle2->Close (Handle2); + + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Get the next node + // + *FilePath = NextDevicePathNode (*FilePath); + } + + // + // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also! + // + *FileHandle = (VOID*)Handle1; + return EFI_SUCCESS; +} diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskHiiStrings.uni refind-0.11.2/filesystems/RamDiskDxe/RamDiskHiiStrings.uni --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskHiiStrings.uni 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskHiiStrings.uni 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,47 @@ +// /** @file +// String definitions for RamDiskDxe driver form. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
        +// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#langdef en-US "English" + +#string STR_FORM_SET_TITLE #language en-US "RAM Disk Configuration" +#string STR_FORM_SET_TITLE_HELP #language en-US "Press to add/remove RAM disks." + +#string STR_MAIN_FORM_TITLE #language en-US "RAM Disk HII Main Screen" +#string STR_RAM_DISK_NULL_STRING #language en-US "" + +#string STR_RAM_DISK_LIST_TEXT #language en-US "Created RAM disk list:" +#string STR_RAM_DISK_LIST_HELP #language en-US "Select for remove" +#string STR_GOTO_ADD_RAW_FORM #language en-US "Create raw" +#string STR_GOTO_ADD_RAW_FORM_HELP #language en-US "Create a raw RAM disk." +#string STR_GOTO_ADD_FROM_FILE_FORM #language en-US "Create from file" +#string STR_GOTO_ADD_FROM_FILE_FORM_HELP #language en-US "Create a RAM disk from a given file." +#string STR_REMOVE_SEL_HELP #language en-US "Remove selected RAM disk(s)" +#string STR_REMOVE_SEL_TEXT #language en-US "Remove selected RAM disk(s)." + +#string STR_ADD_RAW_FORM_TITLE #language en-US "Add A Raw RAM Disk" +#string STR_ADD_RAW_FORM_SUBTITLE_TEXT #language en-US " " + +#string STR_SIZE_PROMPT #language en-US "Size (Hex):" +#string STR_SIZE_HELP #language en-US "The valid RAM disk size should be multiples of the RAM disk block size." + +#string STR_MEMORY_TYPE_PROMPT #language en-US "Disk Memory Type:" +#string STR_MEMORY_TYPE_HELP #language en-US "Specifies type of memory to use from available memory pool in system to create a disk." +#string STR_RAM_DISK_BOOT_SERVICE_DATA_MEMORY #language en-US "Boot Service Data" +#string STR_RAM_DISK_RESERVED_MEMORY #language en-US "Reserved" + +#string STR_CREATE_AND_EXIT_HELP #language en-US "Create a new RAM disk with the given starting and ending address." +#string STR_CREATE_AND_EXIT_PROMPT #language en-US "Create & Exit" +#string STR_DISCARD_AND_EXIT_HELP #language en-US "Discard and exit." +#string STR_DISCARD_AND_EXIT_PROMPT #language en-US "Discard & Exit" diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskHii.vfr refind-0.11.2/filesystems/RamDiskDxe/RamDiskHii.vfr --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskHii.vfr 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskHii.vfr 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,100 @@ +///** @file +// VFR file used by the RamDiskDxe driver. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
        +// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//**/ + +#include "RamDiskNVData.h" + +formset + guid = RAM_DISK_FORM_SET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + // + // Form #1 "Main Form - Add/Remove/Show RAM Disks" + // + form formid = MAIN_FORM_ID, + title = STRING_TOKEN(STR_MAIN_FORM_TITLE); + + oneof + questionid = CREATE_RAW_MEMORY_TYPE_QUESTION_ID, + prompt = STRING_TOKEN(STR_MEMORY_TYPE_PROMPT), + help = STRING_TOKEN(STR_MEMORY_TYPE_HELP), + flags = NUMERIC_SIZE_1 | INTERACTIVE, + option text = STRING_TOKEN(STR_RAM_DISK_BOOT_SERVICE_DATA_MEMORY), value = RAM_DISK_BOOT_SERVICE_DATA_MEMORY, flags = DEFAULT; + option text = STRING_TOKEN(STR_RAM_DISK_RESERVED_MEMORY), value = RAM_DISK_RESERVED_MEMORY, flags = 0; + endoneof; + + subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING); + + goto CREATE_RAW_RAM_DISK_FORM_ID, + prompt = STRING_TOKEN(STR_GOTO_ADD_RAW_FORM), + help = STRING_TOKEN(STR_GOTO_ADD_RAW_FORM_HELP); + + goto MAIN_FORM_ID, + prompt = STRING_TOKEN(STR_GOTO_ADD_FROM_FILE_FORM), + help = STRING_TOKEN(STR_GOTO_ADD_FROM_FILE_FORM_HELP), + flags = INTERACTIVE, + key = MAIN_GOTO_FILE_EXPLORER_ID; + + subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING); + subtitle text = STRING_TOKEN(STR_RAM_DISK_LIST_TEXT); + + label MAIN_LABEL_LIST_START; + label MAIN_LABEL_LIST_END; + + subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING); + + text + help = STRING_TOKEN(STR_REMOVE_SEL_HELP), + text = STRING_TOKEN(STR_REMOVE_SEL_TEXT), + flags = INTERACTIVE, + key = MAIN_REMOVE_RD_QUESTION_ID; + + endform; + + // + // Form #2 "Add New Raw RAM Disk" + // + form formid = CREATE_RAW_RAM_DISK_FORM_ID, + title = STRING_TOKEN(STR_ADD_RAW_FORM_TITLE); + + subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING); + + numeric + questionid = CREATE_RAW_SIZE_QUESTION_ID, + prompt = STRING_TOKEN(STR_SIZE_PROMPT), + help = STRING_TOKEN(STR_SIZE_HELP), + flags = NUMERIC_SIZE_8 | DISPLAY_UINT_HEX | INTERACTIVE, + minimum = 1, + maximum = 0xFFFFFFFFFFFFFFFF, + endnumeric; + + subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING); + + text + help = STRING_TOKEN(STR_CREATE_AND_EXIT_HELP), + text = STRING_TOKEN(STR_CREATE_AND_EXIT_PROMPT), + flags = INTERACTIVE, + key = CREATE_RAW_SUBMIT_QUESTION_ID; + + text + help = STRING_TOKEN(STR_DISCARD_AND_EXIT_HELP), + text = STRING_TOKEN(STR_DISCARD_AND_EXIT_PROMPT), + flags = INTERACTIVE, + key = CREATE_RAW_DISCARD_QUESTION_ID; + + endform; + +endformset; diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskImpl.c refind-0.11.2/filesystems/RamDiskDxe/RamDiskImpl.c --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskImpl.c 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskImpl.c 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,761 @@ +/** @file + HII Config Access protocol implementation of RamDiskDxe driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "RamDiskImpl.h" + +CHAR16 mRamDiskStorageName[] = L"RAM_DISK_CONFIGURATION"; + +RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate = { + RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE, + { + EFI_PAGE_SIZE, + RAM_DISK_BOOT_SERVICE_DATA_MEMORY + }, + { + RamDiskExtractConfig, + RamDiskRouteConfig, + RamDiskCallback + } +}; + +HII_VENDOR_DEVICE_PATH mRamDiskHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + RAM_DISK_FORM_SET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +/** + This function publish the RAM disk configuration Form. + + @param[in, out] ConfigPrivateData + Points to RAM disk configuration private data. + + @retval EFI_SUCCESS HII Form is installed successfully. + @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +InstallRamDiskConfigForm ( + IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + + DriverHandle = NULL; + ConfigAccess = &ConfigPrivateData->ConfigAccess; + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverHandle, + &gEfiDevicePathProtocolGuid, + &mRamDiskHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + ConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ConfigPrivateData->DriverHandle = DriverHandle; + + // + // Publish the HII package list + // + HiiHandle = HiiAddPackages ( + &gRamDiskFormSetGuid, + DriverHandle, + RamDiskDxeStrings, + RamDiskHiiBin, + NULL + ); + if (HiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + &mRamDiskHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + ConfigAccess, + NULL + ); + return EFI_OUT_OF_RESOURCES; + } + + ConfigPrivateData->HiiHandle = HiiHandle; + + return EFI_SUCCESS; +} + + +/** + This function removes RAM disk configuration Form. + + @param[in, out] ConfigPrivateData + Points to RAM disk configuration private data. + +**/ +VOID +UninstallRamDiskConfigForm ( + IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData + ) +{ + // + // Uninstall HII package list + // + if (ConfigPrivateData->HiiHandle != NULL) { + HiiRemovePackages (ConfigPrivateData->HiiHandle); + ConfigPrivateData->HiiHandle = NULL; + } + + // + // Uninstall HII Config Access Protocol + // + if (ConfigPrivateData->DriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + ConfigPrivateData->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mRamDiskHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &ConfigPrivateData->ConfigAccess, + NULL + ); + ConfigPrivateData->DriverHandle = NULL; + } + + FreePool (ConfigPrivateData); +} + + +/** + Unregister all registered RAM disks. + +**/ +VOID +UnregisterAllRamDisks ( + VOID + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + RAM_DISK_PRIVATE_DATA *PrivateData; + + if (!IsListEmpty(&RegisteredRamDisks)) { + EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) { + PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry); + + gBS->UninstallMultipleProtocolInterfaces ( + PrivateData->Handle, + &gEfiBlockIoProtocolGuid, + &PrivateData->BlockIo, + &gEfiBlockIo2ProtocolGuid, + &PrivateData->BlockIo2, + &gEfiDevicePathProtocolGuid, + (EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath, + NULL + ); + + RemoveEntryList (&PrivateData->ThisInstance); + + if (RamDiskCreateHii == PrivateData->CreateMethod) { + // + // If a RAM disk is created within HII, then the RamDiskDxe driver + // driver is responsible for freeing the allocated memory for the + // RAM disk. + // + FreePool ((VOID *)(UINTN) PrivateData->StartingAddr); + } + + FreePool (PrivateData->DevicePath); + FreePool (PrivateData); + } + } +} + + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Request A null-terminated Unicode string in + format. + @param[out] Progress On return, points to a character in the Request + string. Points to the string's null terminator if + request was successful. Points to the most recent + '&' before the first failing name/value pair (or + the beginning of the string if the failure is in + the first name/value pair) if the request was not + successful. + @param[out] Results A null-terminated Unicode string in + format which has all values filled + in for the names in the Request string. String to + be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested + values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in + this driver. + +**/ +EFI_STATUS +EFIAPI +RamDiskExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the offset of + the most recent '&' before the first failing + name/value pair (or the beginning of the string if + the failure is in the first name/value pair) or + the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in + this driver. + +**/ +EFI_STATUS +EFIAPI +RamDiskRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_NOT_FOUND; +} + + +/** + Allocate memory and register the RAM disk created within RamDiskDxe + driver HII. + + @param[in] Size If creating raw, size of the RAM disk to create. + If creating from file, zero. + @param[in] FileHandle If creating raw, NULL. If creating from file, the + file handle. + @param[in] MemoryType Type of memory to be used to create RAM Disk. + + @retval EFI_SUCCESS RAM disk is created and registered. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to match the + size required. + +**/ +EFI_STATUS +HiiCreateRamDisk ( + IN UINT64 Size, + IN EFI_FILE_HANDLE FileHandle, + IN UINT8 MemoryType + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + UINT64 *StartingAddr; + EFI_INPUT_KEY Key; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + RAM_DISK_PRIVATE_DATA *PrivateData; + EFI_FILE_INFO *FileInformation; + + FileInformation = NULL; + StartingAddr = NULL; + + if (FileHandle != NULL) { + // + // Create from file. + // + FileInformation = FileInfo (FileHandle); + if (NULL == FileInformation) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"Not enough memory to get the file information!", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + return EFI_OUT_OF_RESOURCES; + } + + // + // Update the size of RAM disk according to the file size. + // + Size = FileInformation->FileSize; + } + + if (Size > (UINTN) -1) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"The given RAM disk size is too large!", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + return EFI_OUT_OF_RESOURCES; + } + + if (MemoryType == RAM_DISK_BOOT_SERVICE_DATA_MEMORY) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + (UINTN)Size, + (VOID**)&StartingAddr + ); + } else if (MemoryType == RAM_DISK_RESERVED_MEMORY) { + Status = gBS->AllocatePool ( + EfiReservedMemoryType, + (UINTN)Size, + (VOID**)&StartingAddr + ); + } else { + Status = EFI_INVALID_PARAMETER; + } + + if ((StartingAddr == NULL) || EFI_ERROR(Status)) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"Not enough memory to create the RAM disk!", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + return EFI_OUT_OF_RESOURCES; + } + + if (FileHandle != NULL) { + // + // Copy the file content to the RAM disk. + // + BufferSize = (UINTN) Size; + FileHandle->Read ( + FileHandle, + &BufferSize, + (VOID *)(UINTN) StartingAddr + ); + if (BufferSize != FileInformation->FileSize) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"File content read error!", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + return EFI_DEVICE_ERROR; + } + } + + // + // Register the newly created RAM disk. + // + Status = RamDiskRegister ( + ((UINT64)(UINTN) StartingAddr), + Size, + &gEfiVirtualDiskGuid, + NULL, + &DevicePath + ); + if (EFI_ERROR (Status)) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"Fail to register the newly created RAM disk!", + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + return Status; + } + + // + // If RAM disk is created within HII, memory should be freed when the + // RAM disk is unregisterd. + // + PrivateData = RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks.BackLink); + PrivateData->CreateMethod = RamDiskCreateHii; + + return EFI_SUCCESS; +} + + +/** + This function updates the registered RAM disks list on the main form. + + @param[in, out] ConfigPrivate + Private data for configurating hii data for RAM + disks. + +**/ +VOID +UpdateMainForm ( + IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate + ) +{ + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + LIST_ENTRY *Entry; + UINTN Index; + RAM_DISK_PRIVATE_DATA *PrivateData; + CHAR16 *String; + CHAR16 RamDiskStr[128]; + EFI_STRING_ID StringId; + + // + // Init OpCode Handle + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = MAIN_LABEL_LIST_START; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = MAIN_LABEL_LIST_END; + + Index = 0; + EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) { + PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry); + PrivateData->CheckBoxId = (EFI_QUESTION_ID) + (MAIN_CHECKBOX_QUESTION_ID_START + Index); + // + // CheckBox is unchecked by default. + // + PrivateData->CheckBoxChecked = FALSE; + String = RamDiskStr; + + UnicodeSPrint ( + String, + sizeof (RamDiskStr), + L" RAM Disk %d: [0x%lx, 0x%lx]\n", + Index, + PrivateData->StartingAddr, + PrivateData->StartingAddr + PrivateData->Size - 1 + ); + + StringId = HiiSetString (ConfigPrivate->HiiHandle, 0, RamDiskStr, NULL); + ASSERT (StringId != 0); + + HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + PrivateData->CheckBoxId, + 0, + 0, + StringId, + STRING_TOKEN (STR_RAM_DISK_LIST_HELP), + EFI_IFR_FLAG_CALLBACK, + 0, + NULL + ); + + Index++; + } + + HiiUpdateForm ( + ConfigPrivate->HiiHandle, + &gRamDiskFormSetGuid, + MAIN_FORM_ID, + StartOpCodeHandle, + EndOpCodeHandle + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} + + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Action Specifies the type of action taken by the browser. + @param[in] QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param[in] Type The type of value for the question. + @param[in] Value A pointer to the data being sent to the original + exporting driver. + @param[out] ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +EFI_STATUS +EFIAPI +RamDiskCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + RAM_DISK_PRIVATE_DATA *PrivateData; + RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate; + EFI_DEVICE_PATH_PROTOCOL *FileDevPath; + EFI_FILE_HANDLE FileHandle; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + + if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + ConfigPrivate = RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This); + + if (Action == EFI_BROWSER_ACTION_RETRIEVE) { + Status = EFI_UNSUPPORTED; + if (QuestionId == CREATE_RAW_SIZE_QUESTION_ID) { + Value->u64 = EFI_PAGE_SIZE; + ConfigPrivate->ConfigStore.Size = EFI_PAGE_SIZE; + Status = EFI_SUCCESS; + } else if (QuestionId == CREATE_RAW_MEMORY_TYPE_QUESTION_ID) { + Value->u8 = RAM_DISK_BOOT_SERVICE_DATA_MEMORY; + ConfigPrivate->ConfigStore.MemType = RAM_DISK_BOOT_SERVICE_DATA_MEMORY; + Status = EFI_SUCCESS; + } + return Status; + } + + if ((Action != EFI_BROWSER_ACTION_CHANGED) && + (Action != EFI_BROWSER_ACTION_CHANGING) && + (Action != EFI_BROWSER_ACTION_FORM_OPEN)) { + return EFI_UNSUPPORTED; + } + + // + // Update the RAM disk list show at the main form first. + // + if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { + Status = EFI_UNSUPPORTED; + if (QuestionId == MAIN_GOTO_FILE_EXPLORER_ID) { + UpdateMainForm (ConfigPrivate); + Status = EFI_SUCCESS; + } + return Status; + } + + Status = EFI_SUCCESS; + + if (Action == EFI_BROWSER_ACTION_CHANGING) { + switch (QuestionId) { + case MAIN_GOTO_FILE_EXPLORER_ID: + Status = ChooseFile (NULL, NULL, NULL, &FileDevPath); + if (EFI_ERROR (Status)) { + break; + } + + if (FileDevPath != NULL) { + // + // Open the file. + // + Status = OpenFileByDevicePath ( + &FileDevPath, + &FileHandle, + EFI_FILE_MODE_READ, + 0 + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Create from file, RAM disk size is zero. It will be updated + // according to the file size. + // + Status = HiiCreateRamDisk ( + 0, + FileHandle, + ConfigPrivate->ConfigStore.MemType + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Refresh the registered RAM disks list. + // + UpdateMainForm (ConfigPrivate); + } + break; + + default: + break; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + switch (QuestionId) { + case MAIN_REMOVE_RD_QUESTION_ID: + // + // Remove the selected RAM disks + // + EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) { + PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry); + if (PrivateData->CheckBoxChecked) { + RamDiskUnregister ( + (EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath + ); + } + } + + UpdateMainForm (ConfigPrivate); + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + break; + + case CREATE_RAW_SIZE_QUESTION_ID: + ConfigPrivate->ConfigStore.Size = Value->u64; + break; + + case CREATE_RAW_MEMORY_TYPE_QUESTION_ID: + ConfigPrivate->ConfigStore.MemType = Value->u8; + break; + + case CREATE_RAW_SUBMIT_QUESTION_ID: + // + // Create raw, FileHandle is NULL. + // + Status = HiiCreateRamDisk ( + ConfigPrivate->ConfigStore.Size, + NULL, + ConfigPrivate->ConfigStore.MemType + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Refresh the registered RAM disks list. + // + UpdateMainForm (ConfigPrivate); + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; + break; + + case CREATE_RAW_DISCARD_QUESTION_ID: + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; + break; + + default: + // + // QuestionIds for checkboxes + // + if ((QuestionId >= MAIN_CHECKBOX_QUESTION_ID_START) && + (QuestionId < CREATE_RAW_RAM_DISK_FORM_ID)) { + EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) { + PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry); + if (PrivateData->CheckBoxId == QuestionId) { + PrivateData->CheckBoxChecked = (BOOLEAN) (Value->u8 != 0); + } + } + } + break; + } + } + + return EFI_SUCCESS; +} diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskImpl.h refind-0.11.2/filesystems/RamDiskDxe/RamDiskImpl.h --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskImpl.h 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskImpl.h 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,662 @@ +/** @file + The header file of RamDiskDxe driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _RAM_DISK_IMPL_H_ +#define _RAM_DISK_IMPL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "RamDiskNVData.h" + +/// +/// RAM disk general definitions and declarations +/// + +// +// Block size for RAM disk +// +#define RAM_DISK_BLOCK_SIZE 512 + +// +// Iterate through the double linked list. NOT delete safe +// +#define EFI_LIST_FOR_EACH(Entry, ListHead) \ + for(Entry = (ListHead)->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink) + +// +// Iterate through the double linked list. This is delete-safe. +// Do not touch NextEntry +// +#define EFI_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead) \ + for(Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink;\ + Entry != (ListHead); Entry = NextEntry, NextEntry = Entry->ForwardLink) + +// +// RamDiskDxe driver maintains a list of registered RAM disks. +// +extern LIST_ENTRY RegisteredRamDisks; + +// +// Pointers to the EFI_ACPI_TABLE_PROTOCOL and EFI_ACPI_SDT_PROTOCOL. +// +extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol; +extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdtProtocol; + +// +// RAM Disk create method. +// +typedef enum _RAM_DISK_CREATE_METHOD { + RamDiskCreateOthers = 0, + RamDiskCreateHii +} RAM_DISK_CREATE_METHOD; + +// +// RamDiskDxe driver maintains a list of registered RAM disks. +// The struct contains the list entry and the information of each RAM +// disk +// +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_BLOCK_IO2_PROTOCOL BlockIo2; + EFI_BLOCK_IO_MEDIA Media; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + UINT64 StartingAddr; + UINT64 Size; + EFI_GUID TypeGuid; + UINT16 InstanceNumber; + RAM_DISK_CREATE_METHOD CreateMethod; + BOOLEAN InNfit; + EFI_QUESTION_ID CheckBoxId; + BOOLEAN CheckBoxChecked; + + LIST_ENTRY ThisInstance; +} RAM_DISK_PRIVATE_DATA; + +#define RAM_DISK_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('R', 'D', 'S', 'K') +#define RAM_DISK_PRIVATE_FROM_BLKIO(a) CR (a, RAM_DISK_PRIVATE_DATA, BlockIo, RAM_DISK_PRIVATE_DATA_SIGNATURE) +#define RAM_DISK_PRIVATE_FROM_BLKIO2(a) CR (a, RAM_DISK_PRIVATE_DATA, BlockIo2, RAM_DISK_PRIVATE_DATA_SIGNATURE) +#define RAM_DISK_PRIVATE_FROM_THIS(a) CR (a, RAM_DISK_PRIVATE_DATA, ThisInstance, RAM_DISK_PRIVATE_DATA_SIGNATURE) + +/// +/// RAM disk HII-related definitions and declarations +/// + +// +// Tool generated IFR binary data and String package data +// +extern UINT8 RamDiskHiiBin[]; +extern UINT8 RamDiskDxeStrings[]; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +typedef struct { + UINTN Signature; + + RAM_DISK_CONFIGURATION ConfigStore; + + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; +} RAM_DISK_CONFIG_PRIVATE_DATA; + +extern RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate; + +#define RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('R', 'C', 'F', 'G') +#define RAM_DISK_CONFIG_PRIVATE_FROM_THIS(a) CR (a, RAM_DISK_CONFIG_PRIVATE_DATA, ConfigAccess, RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE) + +/** + Register a RAM disk with specified address, size and type. + + @param[in] RamDiskBase The base address of registered RAM disk. + @param[in] RamDiskSize The size of registered RAM disk. + @param[in] RamDiskType The type of registered RAM disk. The GUID can be + any of the values defined in section 9.3.6.9, or a + vendor defined GUID. + @param[in] ParentDevicePath + Pointer to the parent device path. If there is no + parent device path then ParentDevicePath is NULL. + @param[out] DevicePath On return, points to a pointer to the device path + of the RAM disk device. + If ParentDevicePath is not NULL, the returned + DevicePath is created by appending a RAM disk node + to the parent device path. If ParentDevicePath is + NULL, the returned DevicePath is a RAM disk device + path without appending. This function is + responsible for allocating the buffer DevicePath + with the boot service AllocatePool(). + + @retval EFI_SUCCESS The RAM disk is registered successfully. + @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL. + RamDiskSize is 0. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created + is already present in the handle database. + @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to + resource limitation. + +**/ +EFI_STATUS +EFIAPI +RamDiskRegister ( + IN UINT64 RamDiskBase, + IN UINT64 RamDiskSize, + IN EFI_GUID *RamDiskType, + IN EFI_DEVICE_PATH *ParentDevicePath OPTIONAL, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Unregister a RAM disk specified by DevicePath. + + @param[in] DevicePath A pointer to the device path that describes a RAM + Disk device. + + @retval EFI_SUCCESS The RAM disk is unregistered successfully. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_UNSUPPORTED The device specified by DevicePath is not a + valid ramdisk device path and not supported + by the driver. + @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't + exist. + +**/ +EFI_STATUS +EFIAPI +RamDiskUnregister ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Initialize the BlockIO protocol of a RAM disk device. + + @param[in] PrivateData Points to RAM disk private data. + +**/ +VOID +RamDiskInitBlockIo ( + IN RAM_DISK_PRIVATE_DATA *PrivateData + ); + +/** + Reset the Block Device. + + @param[in] This Indicates a pointer to the calling context. + @param[in] ExtendedVerification + Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and + could not be reset. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Read BufferSize bytes from Lba into Buffer. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId Id of the media, changes every time the media is + replaced. + @param[in] Lba The starting Logical Block Address to read from. + @param[in] BufferSize Size of Buffer, must be a multiple of device block + size. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for either having + implicit or explicit ownership of the buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing + the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId does not matched the current + device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block + size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Write BufferSize bytes from Lba into Buffer. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the write request is for. + @param[in] Lba The starting logical block address to be written. + The caller is responsible for writing to only + legitimate locations. + @param[in] BufferSize Size of Buffer, must be a multiple of device block + size. + @param[in] Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing + the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current + device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block + size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not + valid, or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flush the Block Device. + + @param[in] This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding data was written to the device. + @retval EFI_DEVICE_ERROR The device reported an error while writting + back the data + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +/** + Resets the block device hardware. + + @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL. + @param[in] ExtendedVerification The flag about if extend verificate. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The block device is not functioning correctly + and could not be reset. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2Reset ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Reads the requested number of blocks from the device. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the read request is for. + @param[in] Lba The starting logical block address to read + from on the device. + @param[in, out] Token A pointer to the token associated with the + transaction. + @param[in] BufferSize The size of the Buffer in bytes. This must be + a multiple of the intrinsic block size of the + device. + @param[out] Buffer A pointer to the destination buffer for the + data. The caller is responsible for either + having implicit or explicit ownership of the + buffer. + + @retval EFI_SUCCESS The read request was queued if Token->Event + is not NULL. The data was read correctly from + the device if the Token->Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not on proper + alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2ReadBlocksEx ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Writes a specified number of blocks to the device. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the write request is for. + @param[in] Lba The starting logical block address to be + written. The caller is responsible for + writing to only legitimate locations. + @param[in, out] Token A pointer to the token associated with the + transaction. + @param[in] BufferSize The size in bytes of Buffer. This must be a + multiple of the intrinsic block size of the + device. + @param[in] Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The write request was queued if Event is not + NULL. The data was written correctly to the + device if the Event is NULL. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the write operation. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not + valid, or the buffer is not on proper + alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2WriteBlocksEx ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flushes all modified data to a physical block device. + + @param[in] This Indicates a pointer to the calling context. + @param[in, out] Token A pointer to the token associated with the + transaction. + + @retval EFI_SUCCESS The flush request was queued if Event is not + NULL. All outstanding data was written + correctly to the device if the Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to write data. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +RamDiskBlkIo2FlushBlocksEx ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN OUT EFI_BLOCK_IO2_TOKEN *Token + ); + +/** + This function publish the RAM disk configuration Form. + + @param[in, out] ConfigPrivateData + Points to RAM disk configuration private data. + + @retval EFI_SUCCESS HII Form is installed successfully. + @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +InstallRamDiskConfigForm ( + IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData + ); + +/** + This function removes RAM disk configuration Form. + + @param[in, out] ConfigPrivateData + Points to RAM disk configuration private data. + +**/ +VOID +UninstallRamDiskConfigForm ( + IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData + ); + +/** + Unregister all registered RAM disks. + +**/ +VOID +UnregisterAllRamDisks ( + VOID + ); + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Request A null-terminated Unicode string in + format. + @param[out] Progress On return, points to a character in the Request + string. Points to the string's null terminator if + request was successful. Points to the most recent + '&' before the first failing name/value pair (or + the beginning of the string if the failure is in + the first name/value pair) if the request was not + successful. + @param[out] Results A null-terminated Unicode string in + format which has all values filled + in for the names in the Request string. String to + be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested + values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in + this driver. + +**/ +EFI_STATUS +EFIAPI +RamDiskExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the offset of + the most recent '&' before the first failing + name/value pair (or the beginning of the string if + the failure is in the first name/value pair) or + the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in + this driver. + +**/ +EFI_STATUS +EFIAPI +RamDiskRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Action Specifies the type of action taken by the browser. + @param[in] QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param[in] Type The type of value for the question. + @param[in] Value A pointer to the data being sent to the original + exporting driver. + @param[out] ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +EFI_STATUS +EFIAPI +RamDiskCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + + +/** + This function gets the file information from an open file descriptor, + and stores it in a buffer allocated from pool. + + @param[in] FHand File Handle. + + @return A pointer to a buffer with file information or NULL is returned. + +**/ +EFI_FILE_INFO * +FileInfo ( + IN EFI_FILE_HANDLE FHand + ); + + +/** + This function will open a file or directory referenced by DevicePath. + + This function opens a file with the open mode according to the file path. The + Attributes is valid only for EFI_FILE_MODE_CREATE. + + @param[in, out] FilePath On input, the device path to the file. + On output, the remaining device path. + @param[out] FileHandle Pointer to the file handle. + @param[in] OpenMode The mode to open the file with. + @param[in] Attributes The file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or + the medium is no longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open + the file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +OpenFileByDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT EFI_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + + +/** + Publish the RAM disk NVDIMM Firmware Interface Table (NFIT) to the ACPI + table. + + @param[in] PrivateData Points to RAM disk private data. + + @retval EFI_SUCCESS The RAM disk NFIT has been published. + @retval others The RAM disk NFIT has not been published. + +**/ +EFI_STATUS +RamDiskPublishNfit ( + IN RAM_DISK_PRIVATE_DATA *PrivateData + ); + +#endif diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskNVData.h refind-0.11.2/filesystems/RamDiskDxe/RamDiskNVData.h --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskNVData.h 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskNVData.h 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,50 @@ +/** @file + Header file for NV data structure definition. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _RAM_DISK_NVDATA_H_ +#define _RAM_DISK_NVDATA_H_ + +#include +#include + +#define MAIN_FORM_ID 0x1000 +#define MAIN_GOTO_FILE_EXPLORER_ID 0x1001 +#define MAIN_REMOVE_RD_QUESTION_ID 0x1002 +#define MAIN_LABEL_LIST_START 0x1003 +#define MAIN_LABEL_LIST_END 0x1004 +#define MAIN_CHECKBOX_QUESTION_ID_START 0x1100 + +#define CREATE_RAW_RAM_DISK_FORM_ID 0x2000 +#define CREATE_RAW_SIZE_QUESTION_ID 0x2001 +#define CREATE_RAW_SUBMIT_QUESTION_ID 0x2002 +#define CREATE_RAW_DISCARD_QUESTION_ID 0x2003 +#define CREATE_RAW_MEMORY_TYPE_QUESTION_ID 0x2004 + +#define RAM_DISK_BOOT_SERVICE_DATA_MEMORY 0x00 +#define RAM_DISK_RESERVED_MEMORY 0x01 +#define RAM_DISK_MEMORY_TYPE_MAX 0x02 + +typedef struct { + // + // The size of the RAM disk to be created. + // + UINT64 Size; + // + // Selected RAM Disk Memory Type + // + UINT8 MemType; +} RAM_DISK_CONFIGURATION; + +#endif diff -Nru refind-0.10.4/filesystems/RamDiskDxe/RamDiskProtocol.c refind-0.11.2/filesystems/RamDiskDxe/RamDiskProtocol.c --- refind-0.10.4/filesystems/RamDiskDxe/RamDiskProtocol.c 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/RamDiskDxe/RamDiskProtocol.c 2017-05-29 16:44:33.000000000 +0000 @@ -0,0 +1,861 @@ +/** @file + The realization of EFI_RAM_DISK_PROTOCOL. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "RamDiskImpl.h" + +RAM_DISK_PRIVATE_DATA mRamDiskPrivateDataTemplate = { + RAM_DISK_PRIVATE_DATA_SIGNATURE, + NULL +}; + +MEDIA_RAM_DISK_DEVICE_PATH mRamDiskDeviceNodeTemplate = { + { + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + { + (UINT8) (sizeof (MEDIA_RAM_DISK_DEVICE_PATH)), + (UINT8) ((sizeof (MEDIA_RAM_DISK_DEVICE_PATH)) >> 8) + } + } +}; + +BOOLEAN mRamDiskSsdtTableKeyValid = FALSE; +UINTN mRamDiskSsdtTableKey; + + +/** + Initialize the RAM disk device node. + + @param[in] PrivateData Points to RAM disk private data. + @param[in, out] RamDiskDevNode Points to the RAM disk device node. + +**/ +VOID +RamDiskInitDeviceNode ( + IN RAM_DISK_PRIVATE_DATA *PrivateData, + IN OUT MEDIA_RAM_DISK_DEVICE_PATH *RamDiskDevNode + ) +{ + WriteUnaligned64 ( + (UINT64 *) &(RamDiskDevNode->StartingAddr[0]), + (UINT64) PrivateData->StartingAddr + ); + WriteUnaligned64 ( + (UINT64 *) &(RamDiskDevNode->EndingAddr[0]), + (UINT64) PrivateData->StartingAddr + PrivateData->Size - 1 + ); + CopyGuid (&RamDiskDevNode->TypeGuid, &PrivateData->TypeGuid); + RamDiskDevNode->Instance = PrivateData->InstanceNumber; +} + + +/** + Initialize and publish NVDIMM root device SSDT in ACPI table. + + @retval EFI_SUCCESS The NVDIMM root device SSDT is published. + @retval Others The NVDIMM root device SSDT is not published. + +**/ +EFI_STATUS +RamDiskPublishSsdt ( + VOID + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER *Table; + UINTN SectionInstance; + UINTN TableSize; + + Status = EFI_SUCCESS; + SectionInstance = 0; + + // + // Scan all the EFI raw section instances in FV to find the NVDIMM root + // device SSDT. + // + while (TRUE) { + Status = GetSectionFromFv ( + &gEfiCallerIdGuid, + EFI_SECTION_RAW, + SectionInstance, + (VOID **) &Table, + &TableSize + ); + if (EFI_ERROR (Status)) { + break; + } + + if (Table->OemTableId == SIGNATURE_64 ('R', 'a', 'm', 'D', 'i', 's', 'k', ' ')) { + Status = mAcpiTableProtocol->InstallAcpiTable ( + mAcpiTableProtocol, + Table, + TableSize, + &mRamDiskSsdtTableKey + ); + ASSERT_EFI_ERROR (Status); + + if (!EFI_ERROR (Status)) { + mRamDiskSsdtTableKeyValid = TRUE; + } + + FreePool (Table); + return Status; + } else { + FreePool (Table); + SectionInstance++; + } + } + + return Status; +} + + +/** + Publish the RAM disk NVDIMM Firmware Interface Table (NFIT) to the ACPI + table. + + @param[in] PrivateData Points to RAM disk private data. + + @retval EFI_SUCCESS The RAM disk NFIT has been published. + @retval others The RAM disk NFIT has not been published. + +**/ +EFI_STATUS +RamDiskPublishNfit ( + IN RAM_DISK_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; + UINTN TableIndex; + VOID *TableHeader; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableKey; + EFI_ACPI_DESCRIPTION_HEADER *NfitHeader; + EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE + *SpaRange; + VOID *Nfit; + UINT32 NfitLen; + UINTN MemoryMapSize; + UINTN MapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINT64 CurrentData; + UINT8 Checksum; + BOOLEAN MemoryFound; + + // + // Get the EFI memory map. + // + MemoryMapSize = 0; + MemoryMap = NULL; + MemoryFound = FALSE; + + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + do { + MemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (MemoryMapSize); + ASSERT (MemoryMap != NULL); + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (EFI_ERROR (Status)) { + FreePool (MemoryMap); + } + } while (Status == EFI_BUFFER_TOO_SMALL); + ASSERT_EFI_ERROR (Status); + + MemoryMapEntry = MemoryMap; + MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); + while ((UINTN) MemoryMapEntry < (UINTN) MemoryMapEnd) { + if ((MemoryMapEntry->Type == EfiReservedMemoryType) && + (MemoryMapEntry->PhysicalStart <= PrivateData->StartingAddr) && + (MemoryMapEntry->PhysicalStart + + MultU64x32 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SIZE) + >= PrivateData->StartingAddr + PrivateData->Size)) { + MemoryFound = TRUE; + DEBUG (( + EFI_D_INFO, + "RamDiskPublishNfit: RAM disk with reserved meomry type, will publish to NFIT.\n" + )); + break; + } + MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + } + FreePool (MemoryMap); + + if (!MemoryFound) { + return EFI_NOT_FOUND; + } + + // + // Determine whether there is a NFIT already in the ACPI table. + // + Status = EFI_SUCCESS; + TableIndex = 0; + TableKey = 0; + TableHeader = NULL; + + while (!EFI_ERROR (Status)) { + Status = mAcpiSdtProtocol->GetAcpiTable ( + TableIndex, + (EFI_ACPI_SDT_HEADER **)&TableHeader, + &TableVersion, + &TableKey + ); + if (!EFI_ERROR (Status)) { + TableIndex++; + + if (((EFI_ACPI_SDT_HEADER *)TableHeader)->Signature == + EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE) { + break; + } + } + } + + if (!EFI_ERROR (Status)) { + // + // A NFIT is already in the ACPI table. + // + DEBUG (( + EFI_D_INFO, + "RamDiskPublishNfit: A NFIT is already exist in the ACPI Table.\n" + )); + + NfitHeader = (EFI_ACPI_DESCRIPTION_HEADER *)TableHeader; + NfitLen = NfitHeader->Length + sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE); + Nfit = AllocateZeroPool (NfitLen); + if (Nfit == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (Nfit, TableHeader, NfitHeader->Length); + + // + // Update the NFIT head pointer. + // + NfitHeader = (EFI_ACPI_DESCRIPTION_HEADER *)Nfit; + + // + // Uninstall the origin NFIT from the ACPI table. + // + Status = mAcpiTableProtocol->UninstallAcpiTable ( + mAcpiTableProtocol, + TableKey + ); + ASSERT_EFI_ERROR (Status); + + if (EFI_ERROR (Status)) { + FreePool (Nfit); + return Status; + } + + // + // Append the System Physical Address (SPA) Range Structure at the end + // of the origin NFIT. + // + SpaRange = (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *) + ((UINT8 *)Nfit + NfitHeader->Length); + + // + // Update the length field of the NFIT + // + NfitHeader->Length = NfitLen; + + // + // The checksum will be updated after the new contents are appended. + // + NfitHeader->Checksum = 0; + } else { + // + // Assumption is made that if no NFIT is in the ACPI table, there is no + // NVDIMM root device in the \SB scope. + // Therefore, a NVDIMM root device will be reported via Secondary System + // Description Table (SSDT). + // + Status = RamDiskPublishSsdt (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // No NFIT is in the ACPI table, we will create one here. + // + DEBUG (( + EFI_D_INFO, + "RamDiskPublishNfit: No NFIT is in the ACPI Table, will create one.\n" + )); + + NfitLen = sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE) + + sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE); + Nfit = AllocateZeroPool (NfitLen); + if (Nfit == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SpaRange = (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *) + ((UINT8 *)Nfit + sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE)); + + NfitHeader = (EFI_ACPI_DESCRIPTION_HEADER *)Nfit; + NfitHeader->Signature = EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE; + NfitHeader->Length = NfitLen; + NfitHeader->Revision = EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION; + NfitHeader->Checksum = 0; + NfitHeader->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); + NfitHeader->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); + NfitHeader->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); + CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId); + CopyMem (NfitHeader->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (NfitHeader->OemId)); + CopyMem (&NfitHeader->OemTableId, &CurrentData, sizeof (UINT64)); + } + + // + // Fill in the content of the SPA Range Structure. + // + SpaRange->Type = EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE; + SpaRange->Length = sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE); + SpaRange->SystemPhysicalAddressRangeBase = PrivateData->StartingAddr; + SpaRange->SystemPhysicalAddressRangeLength = PrivateData->Size; + CopyGuid (&SpaRange->AddressRangeTypeGUID, &PrivateData->TypeGuid); + + Checksum = CalculateCheckSum8((UINT8 *)Nfit, NfitHeader->Length); + NfitHeader->Checksum = Checksum; + + // + // Publish the NFIT to the ACPI table. + // Note, since the NFIT might be modified by other driver, therefore, we + // do not track the returning TableKey from the InstallAcpiTable(). + // + Status = mAcpiTableProtocol->InstallAcpiTable ( + mAcpiTableProtocol, + Nfit, + NfitHeader->Length, + &TableKey + ); + ASSERT_EFI_ERROR (Status); + + FreePool (Nfit); + + if (EFI_ERROR (Status)) { + return Status; + } + + PrivateData->InNfit = TRUE; + + return EFI_SUCCESS; +} + + +/** + Unpublish the RAM disk NVDIMM Firmware Interface Table (NFIT) from the + ACPI table. + + @param[in] PrivateData Points to RAM disk private data. + + @retval EFI_SUCCESS The RAM disk NFIT has been unpublished. + @retval others The RAM disk NFIT has not been unpublished. + +**/ +EFI_STATUS +RamDiskUnpublishNfit ( + IN RAM_DISK_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status; + UINTN TableIndex; + VOID *TableHeader; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableKey; + EFI_ACPI_DESCRIPTION_HEADER *NewNfitHeader; + EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE + *SpaRange; + VOID *NewNfit; + VOID *NewNfitPtr; + EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER *NfitStructHeader; + UINT32 NewNfitLen; + UINT32 RemainLen; + UINT8 Checksum; + + // + // Find the NFIT in the ACPI table. + // + Status = EFI_SUCCESS; + TableIndex = 0; + TableKey = 0; + TableHeader = NULL; + + while (!EFI_ERROR (Status)) { + Status = mAcpiSdtProtocol->GetAcpiTable ( + TableIndex, + (EFI_ACPI_SDT_HEADER **)&TableHeader, + &TableVersion, + &TableKey + ); + if (!EFI_ERROR (Status)) { + TableIndex++; + + if (((EFI_ACPI_SDT_HEADER *)TableHeader)->Signature == + EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE) { + break; + } + } + } + + if (EFI_ERROR (Status)) { + // + // No NFIT is found in the ACPI table. + // + return EFI_NOT_FOUND; + } + + NewNfitLen = ((EFI_ACPI_DESCRIPTION_HEADER *)TableHeader)->Length - + sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE); + + // + // After removing this RAM disk from the NFIT, if no other structure is in + // the NFIT, we just remove the NFIT and the SSDT which is used to report + // the NVDIMM root device. + // + if (NewNfitLen == sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE)) { + // + // Remove the NFIT. + // + Status = mAcpiTableProtocol->UninstallAcpiTable ( + mAcpiTableProtocol, + TableKey + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Remove the SSDT which is used by RamDiskDxe driver to report the NVDIMM + // root device. + // We do not care the return status since this SSDT might already be + // uninstalled by other drivers to update the information of the NVDIMM + // root device. + // + if (mRamDiskSsdtTableKeyValid) { + mRamDiskSsdtTableKeyValid = FALSE; + + mAcpiTableProtocol->UninstallAcpiTable ( + mAcpiTableProtocol, + mRamDiskSsdtTableKey + ); + } + + return EFI_SUCCESS; + } + + NewNfit = AllocateZeroPool (NewNfitLen); + if (NewNfit == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get a copy of the old NFIT header content. + // + CopyMem (NewNfit, TableHeader, sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE)); + NewNfitHeader = (EFI_ACPI_DESCRIPTION_HEADER *)NewNfit; + NewNfitHeader->Length = NewNfitLen; + NewNfitHeader->Checksum = 0; + + // + // Copy the content of required NFIT structures. + // + NewNfitPtr = (UINT8 *)NewNfit + sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE); + RemainLen = NewNfitLen - sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE); + NfitStructHeader = (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER *) + ((UINT8 *)TableHeader + sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE)); + while (RemainLen > 0) { + if ((NfitStructHeader->Type == EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE) && + (NfitStructHeader->Length == sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE))) { + SpaRange = (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *)NfitStructHeader; + + if ((SpaRange->SystemPhysicalAddressRangeBase == PrivateData->StartingAddr) && + (SpaRange->SystemPhysicalAddressRangeLength == PrivateData->Size) && + (CompareGuid (&SpaRange->AddressRangeTypeGUID, &PrivateData->TypeGuid))) { + // + // Skip the SPA Range Structure for the RAM disk to be unpublished + // from NFIT. + // + NfitStructHeader = (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER *) + ((UINT8 *)NfitStructHeader + NfitStructHeader->Length); + continue; + } + } + + // + // Copy the content of origin NFIT. + // + CopyMem (NewNfitPtr, NfitStructHeader, NfitStructHeader->Length); + NewNfitPtr = (UINT8 *)NewNfitPtr + NfitStructHeader->Length; + + // + // Move to the header of next NFIT structure. + // + RemainLen -= NfitStructHeader->Length; + NfitStructHeader = (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER *) + ((UINT8 *)NfitStructHeader + NfitStructHeader->Length); + } + + Checksum = CalculateCheckSum8((UINT8 *)NewNfit, NewNfitHeader->Length); + NewNfitHeader->Checksum = Checksum; + + Status = mAcpiTableProtocol->UninstallAcpiTable ( + mAcpiTableProtocol, + TableKey + ); + ASSERT_EFI_ERROR (Status); + + if (EFI_ERROR (Status)) { + FreePool (NewNfit); + return Status; + } + + // + // Publish the NFIT to the ACPI table. + // Note, since the NFIT might be modified by other driver, therefore, we + // do not track the returning TableKey from the InstallAcpiTable(). + // + Status = mAcpiTableProtocol->InstallAcpiTable ( + mAcpiTableProtocol, + NewNfit, + NewNfitLen, + &TableKey + ); + ASSERT_EFI_ERROR (Status); + + FreePool (NewNfit); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +/** + Register a RAM disk with specified address, size and type. + + @param[in] RamDiskBase The base address of registered RAM disk. + @param[in] RamDiskSize The size of registered RAM disk. + @param[in] RamDiskType The type of registered RAM disk. The GUID can be + any of the values defined in section 9.3.6.9, or a + vendor defined GUID. + @param[in] ParentDevicePath + Pointer to the parent device path. If there is no + parent device path then ParentDevicePath is NULL. + @param[out] DevicePath On return, points to a pointer to the device path + of the RAM disk device. + If ParentDevicePath is not NULL, the returned + DevicePath is created by appending a RAM disk node + to the parent device path. If ParentDevicePath is + NULL, the returned DevicePath is a RAM disk device + path without appending. This function is + responsible for allocating the buffer DevicePath + with the boot service AllocatePool(). + + @retval EFI_SUCCESS The RAM disk is registered successfully. + @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL. + RamDiskSize is 0. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created + is already present in the handle database. + @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to + resource limitation. + +**/ +EFI_STATUS +EFIAPI +RamDiskRegister ( + IN UINT64 RamDiskBase, + IN UINT64 RamDiskSize, + IN EFI_GUID *RamDiskType, + IN EFI_DEVICE_PATH *ParentDevicePath OPTIONAL, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_STATUS Status; + RAM_DISK_PRIVATE_DATA *PrivateData; + RAM_DISK_PRIVATE_DATA *RegisteredPrivateData; + MEDIA_RAM_DISK_DEVICE_PATH *RamDiskDevNode; + UINTN DevicePathSize; + LIST_ENTRY *Entry; + + if ((0 == RamDiskSize) || (NULL == RamDiskType) || (NULL == DevicePath)) { + return EFI_INVALID_PARAMETER; + } + + // + // Add check to prevent data read across the memory boundary + // + if (RamDiskBase + RamDiskSize > ((UINTN) -1) - RAM_DISK_BLOCK_SIZE + 1) { + return EFI_INVALID_PARAMETER; + } + + RamDiskDevNode = NULL; + + // + // Create a new RAM disk instance and initialize its private data + // + PrivateData = AllocateCopyPool ( + sizeof (RAM_DISK_PRIVATE_DATA), + &mRamDiskPrivateDataTemplate + ); + if (NULL == PrivateData) { + return EFI_OUT_OF_RESOURCES; + } + + PrivateData->StartingAddr = RamDiskBase; + PrivateData->Size = RamDiskSize; + CopyGuid (&PrivateData->TypeGuid, RamDiskType); + InitializeListHead (&PrivateData->ThisInstance); + + // + // Generate device path information for the registered RAM disk + // + RamDiskDevNode = AllocateCopyPool ( + sizeof (MEDIA_RAM_DISK_DEVICE_PATH), + &mRamDiskDeviceNodeTemplate + ); + if (NULL == RamDiskDevNode) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + RamDiskInitDeviceNode (PrivateData, RamDiskDevNode); + + *DevicePath = AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) RamDiskDevNode + ); + if (NULL == *DevicePath) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + PrivateData->DevicePath = *DevicePath; + + // + // Check whether the created device path is already present in the handle + // database + // + if (!IsListEmpty(&RegisteredRamDisks)) { + DevicePathSize = GetDevicePathSize (PrivateData->DevicePath); + + EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) { + RegisteredPrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry); + if (DevicePathSize == GetDevicePathSize (RegisteredPrivateData->DevicePath)) { + // + // Compare device path + // + if ((CompareMem ( + PrivateData->DevicePath, + RegisteredPrivateData->DevicePath, + DevicePathSize)) == 0) { + *DevicePath = NULL; + Status = EFI_ALREADY_STARTED; + goto ErrorExit; + } + } + } + } + + // + // Fill Block IO protocol informations for the RAM disk + // + RamDiskInitBlockIo (PrivateData); + + // + // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL on a new + // handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &PrivateData->Handle, + &gEfiBlockIoProtocolGuid, + &PrivateData->BlockIo, + &gEfiBlockIo2ProtocolGuid, + &PrivateData->BlockIo2, + &gEfiDevicePathProtocolGuid, + PrivateData->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // + // Insert the newly created one to the registered RAM disk list + // + InsertTailList (&RegisteredRamDisks, &PrivateData->ThisInstance); + + gBS->ConnectController (PrivateData->Handle, NULL, NULL, TRUE); + + FreePool (RamDiskDevNode); + + if ((mAcpiTableProtocol != NULL) && (mAcpiSdtProtocol != NULL)) { + RamDiskPublishNfit (PrivateData); + } + + return EFI_SUCCESS; + +ErrorExit: + if (RamDiskDevNode != NULL) { + FreePool (RamDiskDevNode); + } + + if (PrivateData != NULL) { + if (PrivateData->DevicePath) { + FreePool (PrivateData->DevicePath); + } + + FreePool (PrivateData); + } + + return Status; +} + + +/** + Unregister a RAM disk specified by DevicePath. + + @param[in] DevicePath A pointer to the device path that describes a RAM + Disk device. + + @retval EFI_SUCCESS The RAM disk is unregistered successfully. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_UNSUPPORTED The device specified by DevicePath is not a + valid ramdisk device path and not supported + by the driver. + @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't + exist. + +**/ +EFI_STATUS +EFIAPI +RamDiskUnregister ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + BOOLEAN Found; + UINT64 StartingAddr; + UINT64 EndingAddr; + EFI_DEVICE_PATH_PROTOCOL *Header; + MEDIA_RAM_DISK_DEVICE_PATH *RamDiskDevNode; + RAM_DISK_PRIVATE_DATA *PrivateData; + + if (NULL == DevicePath) { + return EFI_INVALID_PARAMETER; + } + + // + // Locate the RAM disk device node. + // + RamDiskDevNode = NULL; + Header = DevicePath; + do { + // + // Test if the current device node is a RAM disk. + // + if ((MEDIA_DEVICE_PATH == Header->Type) && + (MEDIA_RAM_DISK_DP == Header->SubType)) { + RamDiskDevNode = (MEDIA_RAM_DISK_DEVICE_PATH *) Header; + + break; + } + + Header = NextDevicePathNode (Header); + } while ((Header->Type != END_DEVICE_PATH_TYPE)); + + if (NULL == RamDiskDevNode) { + return EFI_UNSUPPORTED; + } + + Found = FALSE; + StartingAddr = ReadUnaligned64 ((UINT64 *) &(RamDiskDevNode->StartingAddr[0])); + EndingAddr = ReadUnaligned64 ((UINT64 *) &(RamDiskDevNode->EndingAddr[0])); + + if (!IsListEmpty(&RegisteredRamDisks)) { + EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) { + PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry); + + // + // Unregister the RAM disk given by its starting address, ending address + // and type guid. + // + if ((StartingAddr == PrivateData->StartingAddr) && + (EndingAddr == PrivateData->StartingAddr + PrivateData->Size - 1) && + (CompareGuid (&RamDiskDevNode->TypeGuid, &PrivateData->TypeGuid))) { + // + // Remove the content for this RAM disk in NFIT. + // + if (PrivateData->InNfit) { + RamDiskUnpublishNfit (PrivateData); + } + + // + // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL + // + gBS->UninstallMultipleProtocolInterfaces ( + PrivateData->Handle, + &gEfiBlockIoProtocolGuid, + &PrivateData->BlockIo, + &gEfiBlockIo2ProtocolGuid, + &PrivateData->BlockIo2, + &gEfiDevicePathProtocolGuid, + (EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath, + NULL + ); + + RemoveEntryList (&PrivateData->ThisInstance); + + if (RamDiskCreateHii == PrivateData->CreateMethod) { + // + // If a RAM disk is created within HII, then the RamDiskDxe driver + // driver is responsible for freeing the allocated memory for the + // RAM disk. + // + FreePool ((VOID *)(UINTN) PrivateData->StartingAddr); + } + + FreePool (PrivateData->DevicePath); + FreePool (PrivateData); + Found = TRUE; + + break; + } + } + } + + if (TRUE == Found) { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} diff -Nru refind-0.10.4/filesystems/reiserfs.inf refind-0.11.2/filesystems/reiserfs.inf --- refind-0.10.4/filesystems/reiserfs.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/filesystems/reiserfs.inf 2017-05-28 13:50:51.000000000 +0000 @@ -0,0 +1,74 @@ +## @file +# +# reiserfs.inf file to build rEFInd's Reiserfs driver using the EDK2/UDK201# +# development kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = reiserfs + FILE_GUID = a62085ec-ab35-4964-bd45-eb0114b13d39 + MODULE_TYPE = UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = fsw_efi_main + FSTYPE = reiserfs + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + fsw_efi.c + fsw_reiserfs.c + fsw_core.c + fsw_efi.c + fsw_lib.c + fsw_efi_lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DxeServicesLib + DxeServicesTableLib + MemoryAllocationLib + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=reiserfs + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO -DFSTYPE=reiserfs + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=reiserfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO -DFSTYPE=reiserfs + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=reiserfs + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO -DFSTYPE=reiserfs diff -Nru refind-0.10.4/filesystems/scandisk.c refind-0.11.2/filesystems/scandisk.c --- refind-0.10.4/filesystems/scandisk.c 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/filesystems/scandisk.c 2017-05-15 00:15:04.000000000 +0000 @@ -24,8 +24,11 @@ #ifdef __MAKEWITH_GNUEFI #include "edk2/DriverBinding.h" #include "edk2/ComponentName.h" -extern EFI_GUID gEfiDiskIoProtocolGuid; -extern EFI_GUID gEfiBlockIoProtocolGuid; +extern EFI_GUID gMyEfiDiskIoProtocolGuid; +extern EFI_GUID gMyEfiBlockIoProtocolGuid; +#else +#define gMyEfiBlockIoProtocolGuid gEfiBlockIoProtocolGuid +#define gMyEfiDiskIoProtocolGuid gEfiDiskIoProtocolGuid #endif #include "../include/refit_call_wrapper.h" @@ -99,16 +102,16 @@ Print(L" "); #endif DPRINT(L"Scanning disks\n"); - Status = refit_call5_wrapper(BS->LocateHandleBuffer, ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &HandleCount, &Handles); + Status = refit_call5_wrapper(BS->LocateHandleBuffer, ByProtocol, &gMyEfiDiskIoProtocolGuid, NULL, &HandleCount, &Handles); if (Status == EFI_NOT_FOUND) return -1; // no filesystems. strange, but true... for (i = 0; i < HandleCount; i++) { EFI_DISK_IO *diskio; EFI_BLOCK_IO *blockio; - Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &gEfiDiskIoProtocolGuid, (VOID **) &diskio); + Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &gMyEfiDiskIoProtocolGuid, (VOID **) &diskio); if (Status != 0) continue; - Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &gEfiBlockIoProtocolGuid, (VOID **) &blockio); + Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &gMyEfiBlockIoProtocolGuid, (VOID **) &blockio); if (Status != 0) continue; struct fsw_volume *vol = create_dummy_volume(diskio, blockio->Media->MediaId); Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/fonts/liberation-mono-regular-28.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/fonts/liberation-mono-regular-28.png differ Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/fonts/nimbus-mono-28.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/fonts/nimbus-mono-28.png differ diff -Nru refind-0.10.4/fonts/README.txt refind-0.11.2/fonts/README.txt --- refind-0.10.4/fonts/README.txt 2015-11-29 23:45:11.000000000 +0000 +++ refind-0.11.2/fonts/README.txt 2017-07-29 14:29:49.000000000 +0000 @@ -2,3 +2,39 @@ serif Liberation Mono Regular and Ubuntu mono and the serif Nimbus Mono, all in 12-, 14, and 24-point versions. All of these font files have anti-aliasing (aka font smoothing) applied. + +New fonts can be created on Linux as follows: + +1. Type "convert -list font | less" to obtain a list of fonts. Search for + monospace fonts. + +2. Type "./mkfont.sh {fontname} {point-size} {offset} {filename}", where: + * {fontname} is the font's name, as shown in the "convert" output. + * {point-size} is the point size, such as 14 or 20. + * {offset} is a positive (to shift down) or negative (to shift up) + integer value by which the font's vertical position is adjusted when + rendered. You'll need to determine this value by trial and error, but + in my experience, most fonts require a -1 or -2 value. + * {filename} is the output filename for a PNG file. + For instance, I used the following command to create the large Liberation + Mono font file: + "./mkfont.sh Liberation-Mono 28 -2 liberation-mono-regular-28.png" + +3. Repeat step #2 as necessary for additional fonts or to try different + {offset} values until you find one that works well for you. + +NOTE TO DEVELOPERS: +------------------- + +When embedding a font in the rEFInd binary as libeg/egemb_font.h or +libeg/egemb_font_large.h, the images/mkegemb.py script is used. This script +is likely to complain of an unsupported format on fonts prepared in this +way. The solution is: + +1. Convert the font to NOT use an alpha layer. (I use xv to load and + re-save the font for this purpose.) +2. Rename the font to font.png or font_large.png (or anything else that + begins with "font", although then additional editing of the resulting + header files will be required). +3. Run mkegemb.py. This causes the script to treat white as if it were + alpha transparency. Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/fonts/ubuntu-mono-28.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/fonts/ubuntu-mono-28.png differ diff -Nru refind-0.10.4/gptsync/gptsync.c refind-0.11.2/gptsync/gptsync.c --- refind-0.10.4/gptsync/gptsync.c 2015-12-06 01:58:58.000000000 +0000 +++ refind-0.11.2/gptsync/gptsync.c 2017-05-26 01:54:17.000000000 +0000 @@ -36,8 +36,9 @@ /* Changes copyright (c) 2013 Roderick W. Smith */ #include "gptsync.h" +#include "../include/version.h" -#include "syslinux_mbr.h" +#include "../include/syslinux_mbr.h" #define memcpy(a, b, c) CopyMem(a, b, c) // diff -Nru refind-0.10.4/gptsync/lib.c refind-0.11.2/gptsync/lib.c --- refind-0.10.4/gptsync/lib.c 2015-12-06 03:07:56.000000000 +0000 +++ refind-0.11.2/gptsync/lib.c 2017-04-18 14:19:28.000000000 +0000 @@ -76,11 +76,11 @@ { 0xa5, STR("FreeBSD") }, { 0xa6, STR("OpenBSD") }, { 0xa7, STR("NeXTSTEP") }, - { 0xa8, STR("Mac OS X UFS") }, + { 0xa8, STR("MacOS UFS") }, { 0xa9, STR("NetBSD") }, - { 0xab, STR("Mac OS X Boot") }, + { 0xab, STR("MacOS Boot") }, { 0xac, STR("Apple RAID") }, - { 0xaf, STR("Mac OS X HFS+") }, + { 0xaf, STR("MacOS HFS+") }, { 0xbe, STR("Solaris Boot") }, { 0xbf, STR("Solaris") }, { 0xeb, STR("BeOS") }, @@ -128,11 +128,11 @@ { "\xC4\x19\xB5\x2D\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0xa9, STR("NetBSD CCD"), GPT_KIND_DATA }, { "\xEC\x19\xB5\x2D\x0E\xB1\xDC\x11\xB9\x9B\x00\x19\xD1\x87\x96\x48", 0xa9, STR("NetBSD CGD"), GPT_KIND_DATA }, // From http://developer.apple.com/mac/library/technotes/tn2006/tn2166.html -// { "\x00\x53\x46\x48\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0x00, STR("Mac OS X HFS+"), GPT_KIND_SYSTEM }, - { "\x00\x53\x46\x48\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xaf, STR("Mac OS X HFS+"), GPT_KIND_DATA }, - { "\x72\x6F\x74\x53\x67\x61\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xaf, STR("Mac OS X Core Storage"), GPT_KIND_DATA }, - { "\x00\x53\x46\x55\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xa8, STR("Mac OS X UFS"), GPT_KIND_DATA }, - { "\x74\x6F\x6F\x42\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xab, STR("Mac OS X Boot"), GPT_KIND_DATA }, +// { "\x00\x53\x46\x48\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0x00, STR("MacOS HFS+"), GPT_KIND_SYSTEM }, + { "\x00\x53\x46\x48\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xaf, STR("MacOS HFS+"), GPT_KIND_DATA }, + { "\x72\x6F\x74\x53\x67\x61\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xaf, STR("MacOS Core Storage"), GPT_KIND_DATA }, + { "\x00\x53\x46\x55\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xa8, STR("MacOS UFS"), GPT_KIND_DATA }, + { "\x74\x6F\x6F\x42\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xab, STR("MacOS Boot"), GPT_KIND_DATA }, { "\x44\x49\x41\x52\x00\x00\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xac, STR("Apple RAID"), GPT_KIND_DATA }, { "\x44\x49\x41\x52\x4F\x5F\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0xac, STR("Apple RAID (Offline)"), GPT_KIND_DATA }, { "\x65\x62\x61\x4C\x00\x6C\xAA\x11\xAA\x11\x00\x30\x65\x43\xEC\xAC", 0x00, STR("Apple Label"), GPT_KIND_SYSTEM }, diff -Nru refind-0.10.4/gptsync/Make.tiano refind-0.11.2/gptsync/Make.tiano --- refind-0.10.4/gptsync/Make.tiano 2015-12-05 23:32:51.000000000 +0000 +++ refind-0.11.2/gptsync/Make.tiano 2017-07-30 19:04:22.000000000 +0000 @@ -6,9 +6,9 @@ include ../Make.common # Below file defines TARGET (RELEASE or DEBUG) and TOOL_CHAIN_TAG (GCC44, GCC45, or GCC46) -#include $(EDK2BASE)/Conf/target.txt +#include $(TIANOBASE)/Conf/target.txt -EFILIB = $(EDK2BASE)/Build/Mde/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH)/MdePkg/Library +EFILIB = $(TIANOBASE)/Build/Mde/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH)/MdePkg/Library ALL_EFILIBS = $(EFILIB)/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib/OUTPUT/BaseDebugPrintErrorLevelLib.lib \ $(EFILIB)/BasePrintLib/BasePrintLib/OUTPUT/BasePrintLib.lib \ $(EFILIB)/BasePcdLibNull/BasePcdLibNull/OUTPUT/BasePcdLibNull.lib \ @@ -26,15 +26,15 @@ ALL_EFILIBS += $(EFILIB)/BaseStackCheckLib/BaseStackCheckLib/OUTPUT/BaseStackCheckLib.lib endif -TIANO_INCLUDE_DIRS = -I $(EDK2BASE)/MdePkg \ - -I $(EDK2BASE)/MdePkg/Include \ - -I $(EDK2BASE)/MdePkg/Include/$(ARCHDIR) \ - -I $(EDK2BASE)/EdkCompatibilityPkg/Foundation/Framework/Include \ - -I $(EDK2BASE)/EdkCompatibilityPkg/Foundation/Library/Dxe/Include \ - -I $(EDK2BASE)/MdeModulePkg/ \ - -I $(EDK2BASE)/MdeModulePkg/Include \ - -I $(EDK2BASE)/IntelFrameworkPkg/Include \ - -I $(EDK2BASE)/MdePkg/Include/$(ARCHDIR) \ +TIANO_INCLUDE_DIRS = -I $(TIANOBASE)/MdePkg \ + -I $(TIANOBASE)/MdePkg/Include \ + -I $(TIANOBASE)/MdePkg/Include/$(ARCHDIR) \ + -I $(TIANOBASE)/EdkCompatibilityPkg/Foundation/Framework/Include \ + -I $(TIANOBASE)/EdkCompatibilityPkg/Foundation/Library/Dxe/Include \ + -I $(TIANOBASE)/MdeModulePkg/ \ + -I $(TIANOBASE)/MdeModulePkg/Include \ + -I $(TIANOBASE)/IntelFrameworkPkg/Include \ + -I $(TIANOBASE)/MdePkg/Include/$(ARCHDIR) \ -I ../libeg \ -I ../include \ -I .. diff -Nru refind-0.10.4/gptsync/os_efi.c refind-0.11.2/gptsync/os_efi.c --- refind-0.10.4/gptsync/os_efi.c 2015-12-06 15:09:08.000000000 +0000 +++ refind-0.11.2/gptsync/os_efi.c 2017-05-25 19:59:16.000000000 +0000 @@ -35,7 +35,7 @@ */ #include "gptsync.h" -#include "refit_call_wrapper.h" +#include "../include/refit_call_wrapper.h" #ifdef __MAKEWITH_TIANO //#include "tiano_includes.h" #include "AutoGen.h" diff -Nru refind-0.10.4/gptsync.inf refind-0.11.2/gptsync.inf --- refind-0.10.4/gptsync.inf 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/gptsync.inf 2017-05-28 18:23:24.000000000 +0000 @@ -0,0 +1,137 @@ +## @file +# +# gptsync.inf file to build gptsync using the EDK2/UDK201# development +# kit. +# +# Copyright (c) 2012-2017 by Roderick W. Smith +# Released under the terms of the GPLv3 (or, at your discretion, any later +# version), a copy of which should come with this file. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = gptsync + FILE_GUID = 2767A966-477A-4EC0-8E95-EFFC2C29583D + MODULE_TYPE = UEFI_APPLICATION + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 + VERSION_STRING = 1.0 + ENTRY_POINT = efi_main + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + gptsync/lib.c + gptsync/gptsync.c + gptsync/os_efi.c + gptsync/showpart.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiLib + UefiApplicationEntryPoint + +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + +[Guids] + gEfiAcpiTableGuid + gEfiAcpi10TableGuid + gEfiAcpi20TableGuid + gEfiDxeServicesTableGuid + gEfiEventReadyToBootGuid + gEfiEventVirtualAddressChangeGuid + gEfiEventExitBootServicesGuid + gEfiFileInfoGuid ## CONSUMES ## GUID + gEfiFileSystemInfoGuid ## CONSUMES ## GUID + gEfiFileSystemVolumeLabelInfoIdGuid + gEfiGlobalVariableGuid + gEfiPartTypeLegacyMbrGuid + gEfiPartTypeSystemPartGuid + gEfiSmbiosTableGuid + gEfiSasDevicePathGuid + +[Ppis] + +[Protocols] + gEfiComponentName2ProtocolGuid # ALWAYS_CONSUMED + gEfiDevicePathToTextProtocolGuid # ALWAYS_CONSUMED + gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED + gEfiSimpleTextInProtocolGuid # ALWAYS_CONSUMED + gEfiSimpleTextInputExProtocolGuid # ALWAYS_CONSUMED + gEfiSimpleTextOutProtocolGuid # ALWAYS_CONSUMED + gEfiUnicodeCollationProtocolGuid # ALWAYS_CONSUMED + gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED + + gEfiAcpiS3SaveProtocolGuid # PROTOCOL CONSUMES + gEfiBlockIoProtocolGuid # PROTOCOL CONSUMES + gEfiCpuArchProtocolGuid # PROTOCOL CONSUMES + gEfiDebugPortProtocolGuid # PROTOCOL CONSUMES + gEfiDevicePathProtocolGuid # PROTOCOL CONSUMES + gEfiDiskIoProtocolGuid # PROTOCOL CONSUMES + gEfiExtScsiPassThruProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + gEfiFirmwareVolume2ProtocolGuid # PROTOCOL CONSUMES + gEfiGraphicsOutputProtocolGuid # PROTOCOL SOMETIMES_CONSUMES + gEfiHiiFontProtocolGuid # PROTOCOL CONSUMES + gEfiLegacy8259ProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + gEfiLoadedImageProtocolGuid # PROTOCOL CONSUMES + gEfiOEMBadgingProtocolGuid # PROTOCOL CONSUMES + gEfiPciIoProtocolGuid # PROTOCOL CONSUMES + gEfiScsiIoProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + gEfiScsiPassThruProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + gEfiSimpleNetworkProtocolGuid # PROTOCOL CONSUMES + gEfiUgaDrawProtocolGuid |PcdUgaConsumeSupport # PROTOCOL SOMETIMES_CONSUMES + + gEfiAbsolutePointerProtocolGuid + gEfiAcpiTableProtocolGuid + gEfiEdidActiveProtocolGuid + gEfiEdidDiscoveredProtocolGuid + gEfiHiiDatabaseProtocolGuid + gEfiHiiImageProtocolGuid + gEfiHiiProtocolGuid + gEfiSimplePointerProtocolGuid + gEfiSmbiosProtocolGuid + gEfiSecurityArchProtocolGuid + gEfiScsiIoProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + gEfiScsiPassThruProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + gEfiExtScsiPassThruProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + + gEfiLegacyBiosProtocolGuid # PROTOCOL TO_START + + gEfiLoadFile2ProtocolGuid + gEfiLoadFileProtocolGuid + gEfiHiiPackageListProtocolGuid + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + +[Pcd] + + +[BuildOptions.IA32] + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO + GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO + +[BuildOptions.X64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO + GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/icons/func_hidden.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/icons/func_hidden.png differ diff -Nru refind-0.10.4/icons/licenses/cc-by-sa-4.0.txt refind-0.11.2/icons/licenses/cc-by-sa-4.0.txt --- refind-0.10.4/icons/licenses/cc-by-sa-4.0.txt 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/icons/licenses/cc-by-sa-4.0.txt 2017-05-08 18:23:17.000000000 +0000 @@ -0,0 +1,428 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/icons/mouse.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/icons/mouse.png differ Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/icons/os_devuan.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/icons/os_devuan.png differ Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/icons/os_trusty.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/icons/os_trusty.png differ Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/icons/os_xenial.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/icons/os_xenial.png differ Binary files /tmp/tmpjI9Vax/2VcpybCGTF/refind-0.10.4/icons/os_zesty.png and /tmp/tmpjI9Vax/lkVVKKMGdA/refind-0.11.2/icons/os_zesty.png differ diff -Nru refind-0.10.4/icons/README refind-0.11.2/icons/README --- refind-0.10.4/icons/README 2016-04-24 17:11:56.000000000 +0000 +++ refind-0.11.2/icons/README 2017-08-12 02:22:15.000000000 +0000 @@ -12,7 +12,7 @@ - Original work for rEFInd - Source: https://sourceforge.net/p/refind (this archive) - - Copyright (c) 2015 by Roderick W. Smith + - Copyright (c) 2015-2017 by Roderick W. Smith - License: LGPLv3+ or CC-SA 3.0 - Debian OS icon @@ -20,11 +20,21 @@ - Copyright (c) 1999 Debian Project - License: LGPLv3+ or CC-SA 3.0 +- Devuan OS icon + - Source: https://devuan.org/ui/img/devuan-emblem.svg + - Copyright (c) 2017 Dyne.org foundation + - License: CC-BY-SA 4.0 + - Elementary OS icon - Source: https://commons.wikimedia.org/wiki/File:Elementary_logo.svg - Copyright (c) 2008 Dan Rabbit - License: GPLv2+ +- Ubuntu "animal" icons + - Source: https://wiki.ubuntu.com/Artwork/Official + - Copyright (c) 2014-2017 Canonical Ltd. + - License: CC-BY-SA 3.0 + Some icons have been altered from their original forms -- normally conversion from SVG to PNG format, resizing, changes in coloration, or addition of "drop shadow" effects. Details follow.... @@ -92,10 +102,18 @@ os_debian.png (LGPLv3+ or CC-BY-SA 3.0) +Modified Ubuntu "animal" icons: + +os_trusty.png +os_xenial.png +os_zesty.png + + Icons created by me (Roderick W. Smith): boot_win.png func_csr_rotate.png +mouse.png os_clover.png os_freebsd.png os_gummiboot.png diff -Nru refind-0.10.4/icons/svg/mouse.svg refind-0.11.2/icons/svg/mouse.svg --- refind-0.10.4/icons/svg/mouse.svg 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/icons/svg/mouse.svg 2017-08-12 02:17:05.000000000 +0000 @@ -0,0 +1,285 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff -Nru refind-0.10.4/icons/svg/os_devuan.svg refind-0.11.2/icons/svg/os_devuan.svg --- refind-0.10.4/icons/svg/os_devuan.svg 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/icons/svg/os_devuan.svg 2017-05-08 18:16:24.000000000 +0000 @@ -0,0 +1,118 @@ + + + + + Devuan Logo + + + + + + + + + + + + + + image/svg+xml + + Devuan Logo + + + hellekin + + + + + Dyne.org Foundation + + + + + hellekin, golinux, Centurion_Dan + + + + + + + + + diff -Nru refind-0.10.4/icons/svg/os_xenial.svg refind-0.11.2/icons/svg/os_xenial.svg --- refind-0.10.4/icons/svg/os_xenial.svg 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/icons/svg/os_xenial.svg 2017-06-13 01:02:05.000000000 +0000 @@ -0,0 +1,128 @@ + + + +image/svg+xml \ No newline at end of file diff -Nru refind-0.10.4/icons/svg/os_zesty.png refind-0.11.2/icons/svg/os_zesty.png --- refind-0.10.4/icons/svg/os_zesty.png 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/icons/svg/os_zesty.png 2017-06-13 01:06:55.000000000 +0000 @@ -0,0 +1,101 @@ + + + +image/svg+xml \ No newline at end of file diff -Nru refind-0.10.4/include/version.h refind-0.11.2/include/version.h --- refind-0.10.4/include/version.h 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/include/version.h 2017-10-22 20:02:35.000000000 +0000 @@ -0,0 +1,14 @@ +/* + * include/version.h + * Version number header file + * + * Copyright (c) 2017 Roderick W. Smith + * + * 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. + * + */ + +#define REFIND_VERSION L"0.11.2" + diff -Nru refind-0.10.4/libeg/egemb_font_large.h refind-0.11.2/libeg/egemb_font_large.h --- refind-0.10.4/libeg/egemb_font_large.h 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/libeg/egemb_font_large.h 2017-07-29 14:27:38.000000000 +0000 @@ -0,0 +1,1431 @@ +static const UINT8 egemb_liberation_mono_regular_28_data[17128] = { + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, + 0xea, 0x00, 0x09, 0x17, 0xff, 0xff, 0x88, 0x00, 0x00, 0x06, 0xff, 0xff, + 0xbf, 0x99, 0x00, 0x02, 0x31, 0xff, 0x31, 0xac, 0x00, 0x03, 0x0d, 0xff, + 0xff, 0xa2, 0x8c, 0x00, 0x04, 0x03, 0x80, 0xff, 0x7f, 0x02, 0x85, 0x00, + 0x03, 0x0d, 0xad, 0xff, 0x58, 0x8d, 0x00, 0x02, 0x42, 0xff, 0x2b, 0xd4, + 0x00, 0x03, 0x45, 0xff, 0xa5, 0x05, 0xff, 0x00, 0xff, 0x00, 0x8f, 0x00, + 0x07, 0x05, 0x37, 0x7d, 0xaa, 0xc4, 0x91, 0x4d, 0x0e, 0xff, 0x00, 0xff, + 0x00, 0xff, 0x00, 0xba, 0x00, 0x00, 0x34, 0x84, 0xff, 0x00, 0x09, 0x81, + 0x00, 0x03, 0x13, 0xd8, 0xff, 0x23, 0x8c, 0x00, 0x00, 0x28, 0x84, 0xff, + 0x00, 0x15, 0xa9, 0x00, 0x03, 0x1e, 0x45, 0x45, 0x1a, 0x98, 0x00, 0x02, + 0x40, 0xff, 0xdd, 0xa5, 0x00, 0x03, 0x19, 0xff, 0xff, 0x22, 0x97, 0x00, + 0x08, 0x2c, 0x6c, 0xa2, 0xca, 0xff, 0xd8, 0xb1, 0x8b, 0x03, 0x91, 0x00, + 0x02, 0x40, 0xff, 0xff, 0x90, 0x00, 0x03, 0x4d, 0xff, 0xff, 0x17, 0x8b, + 0x00, 0x03, 0x26, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, 0x69, + 0x8b, 0x00, 0x00, 0x2d, 0x83, 0xff, 0x00, 0x07, 0xff, 0x00, 0xf7, 0x00, + 0x02, 0x25, 0x7f, 0xca, 0x80, 0xff, 0x00, 0x45, 0x86, 0x00, 0x02, 0x74, + 0xff, 0x4b, 0x86, 0x00, 0x00, 0x70, 0x80, 0xff, 0x02, 0xbd, 0x6c, 0x15, + 0xcc, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x76, 0x80, 0x00, 0x02, 0xd8, 0xff, + 0xa0, 0x99, 0x00, 0x02, 0x31, 0xff, 0x31, 0xac, 0x00, 0x03, 0x05, 0xff, + 0xff, 0x8b, 0x8c, 0x00, 0x03, 0x50, 0xff, 0xb5, 0x0e, 0x87, 0x00, 0x03, + 0x22, 0xea, 0xff, 0x30, 0x8c, 0x00, 0x02, 0x3c, 0xff, 0x25, 0xd3, 0x00, + 0x03, 0x0c, 0xc4, 0xff, 0x32, 0xff, 0x00, 0xff, 0x00, 0x8f, 0x00, 0x09, + 0x18, 0x9f, 0xff, 0x9d, 0x67, 0x5c, 0x88, 0xff, 0xb9, 0x26, 0xff, 0x00, + 0xff, 0x00, 0xff, 0x00, 0xb9, 0x00, 0x03, 0x34, 0xff, 0xff, 0xa5, 0x81, + 0xa3, 0x00, 0x08, 0x82, 0x00, 0x03, 0x54, 0xff, 0x8c, 0x01, 0x8b, 0x00, + 0x00, 0x23, 0x81, 0xa3, 0x03, 0xb1, 0xff, 0xff, 0x15, 0x88, 0x00, 0x03, + 0x07, 0x45, 0x45, 0x3a, 0x9a, 0x00, 0x04, 0x06, 0x61, 0xff, 0xbb, 0x19, + 0x97, 0x00, 0x02, 0x40, 0xff, 0xdd, 0xa5, 0x00, 0x03, 0x19, 0xff, 0xff, + 0x22, 0x96, 0x00, 0x00, 0x55, 0x85, 0xff, 0x00, 0x04, 0x91, 0x00, 0x02, + 0x40, 0xff, 0xff, 0x90, 0x00, 0x03, 0x4d, 0xff, 0xff, 0x17, 0x8b, 0x00, + 0x03, 0x26, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, 0x69, 0x8b, + 0x00, 0x00, 0x29, 0x80, 0xb9, 0x03, 0xc7, 0xff, 0xff, 0x07, 0xff, 0x00, + 0xf6, 0x00, 0x07, 0x21, 0xea, 0xff, 0xff, 0xad, 0xa3, 0xa3, 0x3c, 0x86, + 0x00, 0x02, 0x74, 0xff, 0x4b, 0x86, 0x00, 0x07, 0x5f, 0xa3, 0xa3, 0xb7, + 0xff, 0xff, 0xbb, 0x12, 0xbe, 0x00, 0x02, 0xb3, 0xff, 0x74, 0x87, 0x00, + 0x03, 0x07, 0xff, 0xff, 0x68, 0x80, 0x00, 0x02, 0xb1, 0xff, 0x8b, 0x87, + 0x00, 0x01, 0x9d, 0x5c, 0x81, 0x00, 0x02, 0x36, 0xff, 0x0b, 0x82, 0x00, + 0x0a, 0x06, 0x3c, 0x78, 0xb1, 0xdd, 0xff, 0xdd, 0xb3, 0x78, 0x34, 0x01, + 0x81, 0x00, 0x05, 0x2e, 0x81, 0xb7, 0xb3, 0x79, 0x22, 0x83, 0x00, 0x02, + 0x52, 0xff, 0x3c, 0x83, 0x00, 0x06, 0x2d, 0x76, 0xb7, 0xca, 0x92, 0x51, + 0x0d, 0x89, 0x00, 0x02, 0xd4, 0xff, 0x7a, 0x8b, 0x00, 0x03, 0x20, 0xea, + 0xff, 0x2f, 0x89, 0x00, 0x03, 0x54, 0xff, 0xb9, 0x0e, 0x87, 0x00, 0x09, + 0x03, 0x1b, 0x00, 0x00, 0x36, 0xff, 0x1e, 0x00, 0x01, 0x1a, 0xd0, 0x00, + 0x03, 0x5b, 0xff, 0x89, 0x01, 0x83, 0x00, 0x07, 0x05, 0x3c, 0x7a, 0xb3, + 0xd4, 0xab, 0x6e, 0x2b, 0x89, 0x00, 0x03, 0x0c, 0xaa, 0xff, 0x5c, 0x87, + 0x00, 0x08, 0x07, 0x40, 0x7f, 0xb9, 0xd8, 0xb3, 0x7d, 0x42, 0x08, 0x85, + 0x00, 0x08, 0x0e, 0x4c, 0x87, 0xbd, 0xdd, 0xb9, 0x84, 0x4c, 0x10, 0x8a, + 0x00, 0x03, 0x22, 0xea, 0xff, 0x89, 0x83, 0x00, 0x00, 0x0a, 0x87, 0xff, + 0x00, 0xaa, 0x85, 0x00, 0x07, 0x0a, 0x49, 0x8d, 0xc2, 0xbb, 0x90, 0x54, + 0x0f, 0x83, 0x00, 0x00, 0x92, 0x88, 0xff, 0x00, 0x59, 0x83, 0x00, 0x08, + 0x11, 0x4e, 0x89, 0xbd, 0xd8, 0xb1, 0x7a, 0x3f, 0x08, 0x85, 0x00, 0x07, + 0x09, 0x43, 0x80, 0xb7, 0xd1, 0xa3, 0x64, 0x20, 0xdb, 0x00, 0x08, 0x19, + 0x58, 0x92, 0xc2, 0xd4, 0xaa, 0x74, 0x3c, 0x07, 0x84, 0x00, 0x04, 0x19, + 0xc7, 0xc2, 0x31, 0x01, 0x80, 0x00, 0x03, 0x22, 0xab, 0xcd, 0x1b, 0x85, + 0x00, 0x04, 0x1c, 0xff, 0xff, 0xea, 0x10, 0x85, 0x00, 0x00, 0x80, 0x82, + 0xff, 0x04, 0xd1, 0xad, 0x81, 0x50, 0x18, 0x86, 0x00, 0x07, 0x2a, 0x65, + 0x9f, 0xca, 0xc2, 0x8c, 0x4b, 0x0c, 0x83, 0x00, 0x00, 0x80, 0x80, 0xff, + 0x05, 0xe3, 0xb7, 0x95, 0x62, 0x32, 0x04, 0x84, 0x00, 0x00, 0x80, 0x88, + 0xff, 0x00, 0x80, 0x81, 0x00, 0x00, 0x2d, 0x88, 0xff, 0x00, 0x8d, 0x83, + 0x00, 0x08, 0x01, 0x2e, 0x6a, 0xa3, 0xcd, 0xbf, 0x8a, 0x4b, 0x0d, 0x83, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, + 0x81, 0x00, 0x00, 0x1d, 0x88, 0xff, 0x00, 0x02, 0x85, 0x00, 0x00, 0x31, + 0x83, 0xff, 0x00, 0x43, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, + 0x04, 0x03, 0x7b, 0xff, 0xd8, 0x24, 0x81, 0x00, 0x02, 0x7c, 0xff, 0x98, + 0x89, 0x00, 0x00, 0x1d, 0x80, 0xff, 0x00, 0x18, 0x82, 0x00, 0x00, 0x1e, + 0x80, 0xff, 0x00, 0x04, 0x80, 0x00, 0x03, 0x80, 0xff, 0xff, 0x43, 0x83, + 0x00, 0x02, 0x80, 0xff, 0x53, 0x83, 0x00, 0x07, 0x04, 0x3b, 0x7a, 0xaf, + 0xd1, 0xa6, 0x6d, 0x2d, 0x84, 0x00, 0x00, 0x80, 0x82, 0xff, 0x04, 0xea, + 0xb9, 0x8c, 0x56, 0x1a, 0x85, 0x00, 0x07, 0x02, 0x37, 0x77, 0xad, 0xd1, + 0xa5, 0x69, 0x28, 0x84, 0x00, 0x00, 0x80, 0x83, 0xff, 0x04, 0xc7, 0x9f, + 0x6a, 0x30, 0x02, 0x84, 0x00, 0x08, 0x21, 0x5b, 0x90, 0xbf, 0xdd, 0xbd, + 0x8b, 0x55, 0x17, 0x82, 0x00, 0x00, 0xc2, 0x8a, 0xff, 0x06, 0x78, 0x00, + 0x00, 0x07, 0xff, 0xff, 0x4d, 0x84, 0x00, 0x08, 0x7c, 0xff, 0x8d, 0x00, + 0x00, 0x65, 0xff, 0xd8, 0x0a, 0x86, 0x00, 0x06, 0x23, 0xff, 0xff, 0x3f, + 0xaf, 0xff, 0x60, 0x88, 0x00, 0x07, 0x98, 0xff, 0x6f, 0x00, 0x58, 0xff, + 0xdd, 0x18, 0x84, 0x00, 0x08, 0x31, 0xff, 0xff, 0x35, 0x00, 0x18, 0xd8, + 0xff, 0x59, 0x85, 0x00, 0x06, 0x01, 0x84, 0xff, 0xa8, 0x08, 0x00, 0x00, + 0x8a, 0xff, 0x00, 0x13, 0x83, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x87, + 0x00, 0x03, 0x0a, 0xbb, 0xff, 0x35, 0x90, 0x00, 0x03, 0x26, 0xff, 0xff, + 0x15, 0x88, 0x00, 0x00, 0x3a, 0x80, 0xff, 0x00, 0x16, 0x9b, 0x00, 0x03, + 0x37, 0xcd, 0xb3, 0x16, 0x96, 0x00, 0x02, 0x40, 0xff, 0xdd, 0xa5, 0x00, + 0x03, 0x19, 0xff, 0xff, 0x22, 0x95, 0x00, 0x09, 0x17, 0xff, 0xff, 0x90, + 0x2a, 0x0f, 0x06, 0x06, 0x07, 0x0f, 0x92, 0x00, 0x02, 0x40, 0xff, 0xff, + 0x90, 0x00, 0x03, 0x2b, 0x59, 0x59, 0x0e, 0x8b, 0x00, 0x03, 0x16, 0x59, + 0x59, 0x22, 0x85, 0x00, 0x02, 0x7c, 0xff, 0x69, 0x8f, 0x00, 0x03, 0x34, + 0xff, 0xff, 0x07, 0xff, 0x00, 0x02, 0x37, 0xff, 0x2f, 0xf3, 0x00, 0x03, + 0x8f, 0xff, 0x89, 0x0d, 0x8a, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8a, 0x00, + 0x03, 0x19, 0xb9, 0xff, 0x5c, 0x99, 0x00, 0x08, 0x19, 0x58, 0x92, 0xc2, + 0xd4, 0xaa, 0x74, 0x3c, 0x07, 0x99, 0x00, 0x02, 0xa8, 0xff, 0x6f, 0x88, + 0x00, 0x02, 0xe3, 0xff, 0x5a, 0x80, 0x00, 0x02, 0x98, 0xff, 0x79, 0x86, + 0x00, 0x02, 0x10, 0xff, 0x31, 0x81, 0x00, 0x01, 0x62, 0x92, 0x82, 0x00, + 0x16, 0x12, 0x9d, 0xff, 0xff, 0xb3, 0xa5, 0xff, 0xab, 0xd1, 0xff, 0xff, + 0x78, 0x05, 0x00, 0x00, 0x2a, 0xff, 0xa2, 0x3b, 0x3f, 0xb7, 0xd4, 0x17, + 0x81, 0x00, 0x02, 0x24, 0xff, 0x71, 0x83, 0x00, 0x08, 0x51, 0xff, 0xea, + 0x7f, 0x68, 0xa2, 0xff, 0xb1, 0x10, 0x88, 0x00, 0x02, 0xad, 0xff, 0x6a, + 0x8a, 0x00, 0x03, 0x02, 0x92, 0xff, 0x74, 0x8a, 0x00, 0x03, 0x06, 0xaa, + 0xff, 0x67, 0x87, 0x00, 0x0a, 0x28, 0xff, 0x8a, 0x37, 0x38, 0xff, 0x28, + 0x45, 0x9f, 0xe3, 0x0c, 0xce, 0x00, 0x03, 0x18, 0xe3, 0xff, 0x21, 0x83, + 0x00, 0x01, 0x0e, 0x91, 0x84, 0xff, 0x01, 0x69, 0x04, 0x86, 0x00, 0x04, + 0x22, 0x9c, 0xff, 0xff, 0x5c, 0x86, 0x00, 0x01, 0x17, 0xa2, 0x84, 0xff, + 0x01, 0xad, 0x1a, 0x83, 0x00, 0x01, 0x2e, 0xca, 0x84, 0xff, 0x01, 0xca, + 0x2c, 0x88, 0x00, 0x04, 0x0a, 0xa8, 0xff, 0xff, 0x89, 0x83, 0x00, 0x03, + 0x13, 0xff, 0xff, 0xd1, 0x84, 0xcd, 0x00, 0x9d, 0x84, 0x00, 0x01, 0x21, + 0xb3, 0x83, 0xff, 0x01, 0xbb, 0x1e, 0x82, 0x00, 0x00, 0x8a, 0x86, 0xcd, + 0x02, 0xea, 0xff, 0x58, 0x82, 0x00, 0x0a, 0x35, 0xd1, 0xff, 0xff, 0xa3, + 0x92, 0xb5, 0xff, 0xff, 0xab, 0x1c, 0x83, 0x00, 0x01, 0x1f, 0xaf, 0x84, + 0xff, 0x00, 0x4d, 0xb1, 0x00, 0x01, 0x04, 0x05, 0x90, 0x00, 0x00, 0x08, + 0x8f, 0x00, 0x01, 0x4e, 0xea, 0x84, 0xff, 0x01, 0xad, 0x1d, 0x82, 0x00, + 0x03, 0x08, 0x9f, 0xc7, 0x1b, 0x83, 0x00, 0x03, 0x18, 0xca, 0x8c, 0x01, + 0x84, 0x00, 0x04, 0x5a, 0xff, 0xdd, 0xff, 0x47, 0x85, 0x00, 0x00, 0x80, + 0x87, 0xff, 0x00, 0x4a, 0x83, 0x00, 0x01, 0x07, 0x76, 0x84, 0xff, 0x01, + 0xb7, 0x1f, 0x82, 0x00, 0x00, 0x80, 0x85, 0xff, 0x01, 0xaf, 0x29, 0x83, + 0x00, 0x00, 0x80, 0x88, 0xff, 0x00, 0x80, 0x81, 0x00, 0x00, 0x2d, 0x88, + 0xff, 0x00, 0x8d, 0x82, 0x00, 0x01, 0x09, 0x80, 0x84, 0xff, 0x01, 0xbf, + 0x2a, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, + 0xff, 0x53, 0x81, 0x00, 0x00, 0x1d, 0x88, 0xff, 0x00, 0x02, 0x85, 0x00, + 0x00, 0x31, 0x83, 0xff, 0x00, 0x43, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x83, 0x00, 0x03, 0x63, 0xff, 0xea, 0x30, 0x82, 0x00, 0x02, 0x7c, 0xff, + 0x98, 0x89, 0x00, 0x00, 0x1d, 0x80, 0xff, 0x00, 0x53, 0x82, 0x00, 0x00, + 0x5d, 0x80, 0xff, 0x00, 0x04, 0x80, 0x00, 0x04, 0x80, 0xff, 0xff, 0xaf, + 0x05, 0x82, 0x00, 0x02, 0x80, 0xff, 0x53, 0x82, 0x00, 0x01, 0x12, 0x9a, + 0x84, 0xff, 0x01, 0x75, 0x06, 0x82, 0x00, 0x00, 0x80, 0x87, 0xff, 0x00, + 0x52, 0x83, 0x00, 0x01, 0x0c, 0x8c, 0x84, 0xff, 0x01, 0x66, 0x03, 0x82, + 0x00, 0x00, 0x80, 0x87, 0xff, 0x01, 0x87, 0x0b, 0x81, 0x00, 0x01, 0x01, + 0x5f, 0x81, 0xff, 0x00, 0xd8, 0x80, 0xff, 0x01, 0xea, 0x3f, 0x81, 0x00, + 0x00, 0xc2, 0x8a, 0xff, 0x06, 0x78, 0x00, 0x00, 0x07, 0xff, 0xff, 0x4d, + 0x84, 0x00, 0x08, 0x7c, 0xff, 0x8d, 0x00, 0x00, 0x24, 0xff, 0xff, 0x3a, + 0x86, 0x00, 0x06, 0x5f, 0xff, 0xd8, 0x0b, 0x7a, 0xff, 0x7f, 0x87, 0x00, + 0x09, 0x01, 0xd4, 0xff, 0x4f, 0x00, 0x06, 0x99, 0xff, 0x89, 0x02, 0x82, + 0x00, 0x03, 0x0b, 0xb5, 0xff, 0x6e, 0x80, 0x00, 0x03, 0x4b, 0xff, 0xea, + 0x1e, 0x84, 0x00, 0x03, 0x3b, 0xff, 0xff, 0x2a, 0x80, 0x00, 0x8a, 0xff, + 0x00, 0x12, 0x83, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x88, 0x00, 0x03, + 0x3f, 0xff, 0xab, 0x06, 0x8f, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x88, + 0x00, 0x04, 0x91, 0xea, 0x4e, 0xff, 0x56, 0x9c, 0x00, 0x03, 0x19, 0x99, + 0xab, 0x0f, 0x95, 0x00, 0x02, 0x40, 0xff, 0xdd, 0xa5, 0x00, 0x03, 0x19, + 0xff, 0xff, 0x22, 0x95, 0x00, 0x03, 0x3a, 0xff, 0xff, 0x17, 0x98, 0x00, + 0x02, 0x40, 0xff, 0xff, 0xae, 0x00, 0x02, 0x7c, 0xff, 0x69, 0x8f, 0x00, + 0x03, 0x34, 0xff, 0xff, 0x07, 0xff, 0x00, 0x02, 0x68, 0xff, 0x2f, 0xf2, + 0x00, 0x03, 0x0a, 0xff, 0xff, 0x31, 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, + 0x8b, 0x00, 0x02, 0x55, 0xff, 0x98, 0x98, 0x00, 0x01, 0x4e, 0xea, 0x84, + 0xff, 0x01, 0xad, 0x1d, 0x98, 0x00, 0x02, 0x9d, 0xff, 0x68, 0x88, 0x00, + 0x02, 0xb5, 0xff, 0x4e, 0x80, 0x00, 0x02, 0x84, 0xff, 0x6a, 0x86, 0x00, + 0x02, 0x32, 0xff, 0x10, 0x81, 0x00, 0x01, 0xa6, 0x57, 0x82, 0x00, 0x16, + 0x7e, 0xff, 0xab, 0x22, 0x00, 0x31, 0xff, 0x31, 0x03, 0x41, 0xff, 0xff, + 0x4d, 0x00, 0x00, 0x7e, 0xff, 0x22, 0x00, 0x00, 0x39, 0xff, 0x58, 0x80, + 0x00, 0x03, 0x0a, 0xaa, 0xaf, 0x0c, 0x82, 0x00, 0x09, 0x15, 0xff, 0xcd, + 0x1f, 0x00, 0x00, 0x03, 0x74, 0xff, 0x54, 0x88, 0x00, 0x02, 0x95, 0xff, + 0x5d, 0x8a, 0x00, 0x03, 0x38, 0xff, 0xea, 0x17, 0x8b, 0x00, 0x03, 0x35, + 0xff, 0xff, 0x1c, 0x86, 0x00, 0x02, 0x22, 0x6b, 0xbb, 0x82, 0xff, 0x02, + 0xa6, 0x5f, 0x13, 0x87, 0x00, 0x02, 0x33, 0x5f, 0x1f, 0xc1, 0x00, 0x02, + 0x76, 0xff, 0x6d, 0x83, 0x00, 0x0b, 0x01, 0x80, 0xff, 0xbd, 0x37, 0x0a, + 0x01, 0x0f, 0x4b, 0xea, 0xff, 0x4f, 0x82, 0x00, 0x08, 0x06, 0x14, 0x33, + 0x74, 0xff, 0xbd, 0xb1, 0xff, 0x5c, 0x85, 0x00, 0x0c, 0x06, 0xa3, 0xff, + 0xbf, 0x3f, 0x11, 0x06, 0x15, 0x4a, 0xd8, 0xff, 0xa2, 0x05, 0x81, 0x00, + 0x0c, 0x1b, 0xd8, 0xff, 0x92, 0x2e, 0x0e, 0x05, 0x11, 0x3a, 0xb7, 0xff, + 0xc7, 0x0d, 0x87, 0x00, 0x04, 0x6e, 0xff, 0xbf, 0xff, 0x89, 0x83, 0x00, + 0x03, 0x1b, 0xff, 0xff, 0x16, 0x8b, 0x00, 0x0b, 0x14, 0xc2, 0xff, 0x88, + 0x22, 0x04, 0x06, 0x29, 0xa5, 0xff, 0xa5, 0x05, 0x8a, 0x00, 0x03, 0x14, + 0xca, 0xe3, 0x1b, 0x81, 0x00, 0x04, 0x1c, 0xea, 0xff, 0x73, 0x12, 0x80, + 0x00, 0x04, 0x1e, 0xa0, 0xff, 0xad, 0x07, 0x81, 0x00, 0x0b, 0x0f, 0xbb, + 0xff, 0xaf, 0x31, 0x08, 0x02, 0x1a, 0x77, 0xff, 0xff, 0x35, 0xae, 0x00, + 0x03, 0x10, 0x4c, 0xb3, 0x17, 0x90, 0x00, 0x03, 0x36, 0x98, 0x3c, 0x08, + 0x8b, 0x00, 0x0c, 0x4a, 0xff, 0xff, 0x83, 0x29, 0x0c, 0x0b, 0x1b, 0x4f, + 0xc4, 0xff, 0xb5, 0x0b, 0x81, 0x00, 0x02, 0x4b, 0xff, 0x38, 0x85, 0x00, + 0x02, 0x4a, 0xff, 0x29, 0x83, 0x00, 0x06, 0x06, 0xbf, 0xff, 0x50, 0xff, + 0x9f, 0x01, 0x84, 0x00, 0x02, 0x80, 0xff, 0x91, 0x80, 0x09, 0x06, 0x0c, + 0x19, 0x3c, 0xab, 0xff, 0xff, 0x22, 0x81, 0x00, 0x0c, 0x01, 0x7b, 0xff, + 0xff, 0x7b, 0x2a, 0x14, 0x18, 0x47, 0xc7, 0xff, 0xbb, 0x17, 0x81, 0x00, + 0x0b, 0x80, 0xff, 0x92, 0x0d, 0x0e, 0x16, 0x2a, 0x5b, 0xcd, 0xff, 0xff, + 0x34, 0x82, 0x00, 0x02, 0x80, 0xff, 0x92, 0x86, 0x0d, 0x00, 0x0a, 0x81, + 0x00, 0x03, 0x2d, 0xff, 0xff, 0x2d, 0x85, 0x0d, 0x00, 0x0b, 0x81, 0x00, + 0x0c, 0x02, 0x84, 0xff, 0xff, 0x72, 0x27, 0x13, 0x1b, 0x3f, 0xb1, 0xff, + 0xd4, 0x19, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, + 0xff, 0xff, 0x53, 0x81, 0x00, 0x00, 0x03, 0x81, 0x0d, 0x02, 0xb5, 0xff, + 0x70, 0x81, 0x0d, 0x86, 0x00, 0x00, 0x05, 0x80, 0x0d, 0x03, 0x19, 0xff, + 0xff, 0x43, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x82, 0x00, 0x03, 0x4b, + 0xff, 0xff, 0x3e, 0x83, 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x05, + 0x1d, 0xff, 0xc2, 0xe3, 0xb7, 0x04, 0x80, 0x00, 0x05, 0x06, 0xc4, 0xbd, + 0xff, 0xff, 0x04, 0x80, 0x00, 0x00, 0x80, 0x80, 0xff, 0x00, 0x3b, 0x82, + 0x00, 0x02, 0x80, 0xff, 0x53, 0x81, 0x00, 0x0b, 0x06, 0xa0, 0xff, 0xff, + 0x5a, 0x1e, 0x13, 0x25, 0x76, 0xff, 0xff, 0x70, 0x82, 0x00, 0x02, 0x80, + 0xff, 0x91, 0x80, 0x09, 0x06, 0x0b, 0x16, 0x36, 0x96, 0xff, 0xff, 0x44, + 0x81, 0x00, 0x0b, 0x03, 0x8c, 0xff, 0xff, 0x60, 0x1f, 0x13, 0x27, 0x7d, + 0xff, 0xff, 0x5c, 0x82, 0x00, 0x02, 0x80, 0xff, 0x91, 0x80, 0x09, 0x06, + 0x0a, 0x11, 0x27, 0x6f, 0xff, 0xff, 0x71, 0x81, 0x00, 0x0c, 0x41, 0xff, + 0xff, 0x69, 0x1a, 0x03, 0x00, 0x06, 0x2f, 0x9f, 0xff, 0xff, 0x20, 0x80, + 0x00, 0x00, 0x0c, 0x82, 0x0d, 0x02, 0xad, 0xff, 0x70, 0x82, 0x0d, 0x06, + 0x0a, 0x00, 0x00, 0x07, 0xff, 0xff, 0x4d, 0x84, 0x00, 0x08, 0x7c, 0xff, + 0x8d, 0x00, 0x00, 0x01, 0xa3, 0xff, 0x84, 0x85, 0x00, 0x07, 0x05, 0xc2, + 0xff, 0x6b, 0x00, 0x57, 0xff, 0xab, 0x87, 0x00, 0x09, 0x0e, 0xff, 0xff, + 0x34, 0x00, 0x00, 0x1d, 0xe3, 0xff, 0x42, 0x82, 0x00, 0x03, 0x68, 0xff, + 0xaf, 0x0b, 0x80, 0x00, 0x04, 0x04, 0x94, 0xff, 0x90, 0x03, 0x82, 0x00, + 0x03, 0x0d, 0xbf, 0xff, 0x67, 0x81, 0x00, 0x86, 0x0d, 0x03, 0x24, 0xd4, + 0xff, 0x62, 0x84, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x88, 0x00, 0x03, + 0x04, 0x9d, 0xff, 0x4a, 0x8f, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x87, + 0x00, 0x06, 0x20, 0xff, 0x72, 0x06, 0xbf, 0xbf, 0x06, 0xb7, 0x00, 0x02, + 0x40, 0xff, 0xdd, 0xa5, 0x00, 0x03, 0x19, 0xff, 0xff, 0x22, 0x95, 0x00, + 0x02, 0x48, 0xff, 0xcd, 0x99, 0x00, 0x02, 0x40, 0xff, 0xff, 0xae, 0x00, + 0x02, 0x7c, 0xff, 0x69, 0x8f, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0xfe, + 0x00, 0x03, 0x01, 0xb7, 0xff, 0x2f, 0xf2, 0x00, 0x03, 0x11, 0xff, 0xff, + 0x21, 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x40, 0xff, + 0xaf, 0x97, 0x00, 0x0c, 0x4a, 0xff, 0xff, 0x83, 0x29, 0x0c, 0x0b, 0x1b, + 0x4f, 0xc4, 0xff, 0xb5, 0x0b, 0x97, 0x00, 0x02, 0x95, 0xff, 0x63, 0x88, + 0x00, 0x02, 0x99, 0xff, 0x43, 0x80, 0x00, 0x02, 0x74, 0xff, 0x5c, 0x86, + 0x00, 0x01, 0x5d, 0x9f, 0x81, 0x00, 0x02, 0x12, 0xff, 0x2d, 0x81, 0x00, + 0x17, 0x0e, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x31, 0xff, 0x31, 0x00, 0x00, + 0x55, 0xff, 0xb7, 0x04, 0x00, 0xbf, 0xff, 0x06, 0x00, 0x00, 0x18, 0xff, + 0x82, 0x80, 0x00, 0x02, 0x6a, 0xff, 0x28, 0x83, 0x00, 0x02, 0x34, 0xff, + 0x68, 0x81, 0x00, 0x02, 0x32, 0xff, 0x70, 0x88, 0x00, 0x02, 0x81, 0xff, + 0x50, 0x89, 0x00, 0x03, 0x01, 0x9a, 0xff, 0x6f, 0x8c, 0x00, 0x03, 0x03, + 0xaa, 0xff, 0x68, 0x88, 0x00, 0x05, 0x01, 0x20, 0xc7, 0xff, 0x8f, 0x14, + 0x8a, 0x00, 0x02, 0x59, 0xff, 0x34, 0xc0, 0x00, 0x03, 0x27, 0xff, 0xdd, + 0x14, 0x83, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x25, 0x82, 0x00, 0x03, 0x49, + 0xff, 0xe3, 0x0f, 0x81, 0x00, 0x00, 0xcd, 0x80, 0xff, 0x04, 0x89, 0x1a, + 0x92, 0xff, 0x5c, 0x85, 0x00, 0x03, 0x3e, 0xff, 0xff, 0x27, 0x82, 0x00, + 0x03, 0x3c, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x03, 0x68, 0xff, 0xab, 0x0a, + 0x82, 0x00, 0x03, 0x28, 0xff, 0xff, 0x37, 0x86, 0x00, 0x05, 0x3a, 0xff, + 0x6f, 0x63, 0xff, 0x89, 0x83, 0x00, 0x03, 0x25, 0xff, 0xff, 0x0c, 0x8b, + 0x00, 0x03, 0x73, 0xff, 0x8b, 0x06, 0x81, 0x00, 0x03, 0x17, 0xb5, 0x81, + 0x1c, 0x89, 0x00, 0x03, 0x02, 0x82, 0xff, 0x4f, 0x82, 0x00, 0x03, 0x5b, + 0xff, 0xbf, 0x06, 0x82, 0x00, 0x03, 0x26, 0xff, 0xff, 0x30, 0x81, 0x00, + 0x03, 0x57, 0xff, 0xea, 0x1b, 0x81, 0x00, 0x04, 0x02, 0x78, 0xff, 0xb1, + 0x03, 0x85, 0x00, 0x00, 0x1b, 0x80, 0xff, 0x8a, 0x00, 0x00, 0x1b, 0x80, + 0xff, 0x8e, 0x00, 0x05, 0x24, 0x6d, 0xe3, 0xff, 0xea, 0x14, 0x90, 0x00, + 0x05, 0x31, 0xff, 0xff, 0xc7, 0x59, 0x18, 0x88, 0x00, 0x04, 0x11, 0xdd, + 0xff, 0x6c, 0x01, 0x82, 0x00, 0x03, 0x22, 0xff, 0xff, 0x40, 0x80, 0x00, + 0x0e, 0x08, 0xc2, 0x94, 0x00, 0x00, 0x13, 0x6e, 0xc4, 0x96, 0x24, 0x22, + 0xff, 0x36, 0xea, 0x63, 0x83, 0x00, 0x06, 0x33, 0xff, 0x9d, 0x07, 0xca, + 0xff, 0x22, 0x84, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x1c, + 0xff, 0xff, 0x50, 0x81, 0x00, 0x04, 0x33, 0xff, 0xff, 0x66, 0x01, 0x81, + 0x00, 0x03, 0x17, 0xbd, 0xff, 0x7c, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x82, 0x00, 0x04, 0x15, 0xa0, 0xff, 0xd1, 0x13, 0x81, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x8b, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x22, 0x8a, 0x00, 0x03, + 0x38, 0xff, 0xff, 0x5b, 0x82, 0x00, 0x03, 0x13, 0xb3, 0xff, 0x75, 0x81, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, + 0x86, 0x00, 0x02, 0xb1, 0xff, 0x69, 0x8e, 0x00, 0x03, 0x0d, 0xff, 0xff, + 0x43, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x81, 0x00, 0x03, 0x35, 0xff, + 0xff, 0x4e, 0x84, 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x05, 0x1d, + 0xff, 0xad, 0x76, 0xff, 0x2e, 0x80, 0x00, 0x05, 0x35, 0xff, 0x65, 0xff, + 0xff, 0x04, 0x80, 0x00, 0x05, 0x80, 0xff, 0x7f, 0xff, 0xa2, 0x02, 0x81, + 0x00, 0x02, 0x80, 0xff, 0x53, 0x81, 0x00, 0x03, 0x4d, 0xff, 0xff, 0x3f, + 0x82, 0x00, 0x03, 0x6a, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x02, 0x80, 0xff, + 0x8d, 0x83, 0x00, 0x04, 0x07, 0x95, 0xff, 0xbf, 0x03, 0x80, 0x00, 0x03, + 0x3d, 0xff, 0xff, 0x4b, 0x81, 0x00, 0x04, 0x02, 0x77, 0xff, 0xff, 0x1e, + 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x69, 0xff, 0xff, + 0x10, 0x80, 0x00, 0x03, 0x99, 0xff, 0x88, 0x01, 0x82, 0x00, 0x03, 0x12, + 0xd1, 0xff, 0x6f, 0x86, 0x00, 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, 0x03, + 0x07, 0xff, 0xff, 0x4d, 0x84, 0x00, 0x02, 0x7c, 0xff, 0x8d, 0x80, 0x00, + 0x03, 0x49, 0xff, 0xff, 0x14, 0x84, 0x00, 0x08, 0x2f, 0xff, 0xff, 0x28, + 0x00, 0x3b, 0xff, 0xff, 0x06, 0x86, 0x00, 0x03, 0x1f, 0xff, 0xff, 0x1d, + 0x80, 0x00, 0x03, 0x4a, 0xff, 0xcd, 0x13, 0x80, 0x00, 0x03, 0x2b, 0xff, + 0xff, 0x29, 0x82, 0x00, 0x03, 0x1e, 0xea, 0xff, 0x43, 0x82, 0x00, 0x03, + 0x69, 0xff, 0xb5, 0x0b, 0x89, 0x00, 0x04, 0x08, 0x98, 0xff, 0x89, 0x05, + 0x84, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x89, 0x00, 0x03, 0x2d, 0xff, + 0xca, 0x0e, 0x8e, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x87, 0x00, 0x06, + 0x66, 0xff, 0x29, 0x00, 0x58, 0xff, 0x38, 0xa8, 0x00, 0x07, 0x1a, 0x5c, + 0x96, 0xc7, 0xd4, 0xa3, 0x68, 0x21, 0x84, 0x00, 0x0a, 0x40, 0xff, 0xdd, + 0x00, 0x12, 0x5a, 0x9f, 0xd1, 0xaa, 0x63, 0x15, 0x85, 0x00, 0x08, 0x03, + 0x34, 0x71, 0xaa, 0xd4, 0xb9, 0x7e, 0x3f, 0x06, 0x85, 0x00, 0x0a, 0x22, + 0x70, 0xb3, 0xcd, 0x9c, 0x57, 0x0f, 0x19, 0xff, 0xff, 0x22, 0x83, 0x00, + 0x08, 0x05, 0x3a, 0x79, 0xb3, 0xd4, 0xaa, 0x73, 0x32, 0x01, 0x82, 0x00, + 0x00, 0x0d, 0x89, 0xff, 0x00, 0x5f, 0x83, 0x00, 0x0a, 0x1d, 0x6a, 0xab, + 0xcd, 0x98, 0x4b, 0x08, 0x00, 0xdd, 0xff, 0x31, 0x81, 0x00, 0x0a, 0x40, + 0xff, 0xdd, 0x00, 0x10, 0x56, 0x99, 0xcd, 0xb1, 0x6c, 0x1d, 0x84, 0x00, + 0x00, 0x5f, 0x83, 0xff, 0x00, 0x17, 0x86, 0x00, 0x00, 0x56, 0x84, 0xff, + 0x00, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, 0x69, 0x82, 0x00, 0x03, 0x23, + 0xd4, 0xff, 0x56, 0x86, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x84, 0x00, + 0x0d, 0x5b, 0xff, 0x38, 0x18, 0x80, 0xc2, 0x7e, 0x11, 0x00, 0x30, 0x98, + 0xcd, 0x80, 0x14, 0x81, 0x00, 0x0a, 0x49, 0xff, 0x84, 0x00, 0x0f, 0x53, + 0x96, 0xca, 0xb5, 0x71, 0x21, 0x85, 0x00, 0x08, 0x05, 0x3d, 0x7c, 0xb1, + 0xd4, 0xad, 0x76, 0x39, 0x04, 0x83, 0x00, 0x0a, 0x49, 0xff, 0x9f, 0x00, + 0x13, 0x5e, 0xa3, 0xd1, 0xa8, 0x62, 0x16, 0x85, 0x00, 0x0a, 0x22, 0x71, + 0xb3, 0xca, 0x9a, 0x56, 0x0e, 0x0d, 0xff, 0xff, 0x2a, 0x82, 0x00, 0x0b, + 0x52, 0xff, 0x7b, 0x00, 0x00, 0x16, 0x67, 0xb1, 0xea, 0xff, 0xff, 0x24, + 0x83, 0x00, 0x08, 0x09, 0x47, 0x83, 0xb9, 0xd4, 0xa6, 0x7c, 0x3a, 0x08, + 0x83, 0x00, 0x00, 0x36, 0x87, 0xff, 0x00, 0x22, 0x82, 0x00, 0x02, 0x40, + 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x80, 0x00, 0x03, + 0x98, 0xff, 0x9f, 0x01, 0x84, 0x00, 0x07, 0x0d, 0xe3, 0xff, 0x5f, 0x00, + 0x5f, 0xff, 0x83, 0x87, 0x00, 0x08, 0x01, 0xc7, 0xff, 0x39, 0x00, 0x12, + 0xbf, 0xff, 0x58, 0x83, 0x00, 0x09, 0x06, 0x9c, 0xff, 0x7f, 0x02, 0x00, + 0x01, 0x9a, 0xff, 0x74, 0x85, 0x00, 0x03, 0x02, 0xa6, 0xff, 0x65, 0x80, + 0x00, 0x00, 0x3b, 0x88, 0xff, 0x00, 0x0b, 0x85, 0x00, 0x03, 0x11, 0xff, + 0xff, 0x1f, 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x3d, + 0xff, 0xb1, 0x96, 0x00, 0x04, 0x11, 0xdd, 0xff, 0x6c, 0x01, 0x82, 0x00, + 0x03, 0x22, 0xff, 0xff, 0x40, 0x97, 0x00, 0x02, 0x8c, 0xff, 0x5e, 0x88, + 0x00, 0x02, 0x85, 0xff, 0x38, 0x80, 0x00, 0x02, 0x66, 0xff, 0x50, 0x82, + 0x00, 0x00, 0x09, 0x80, 0x11, 0x01, 0x9f, 0x6c, 0x81, 0x11, 0x23, 0x3f, + 0xff, 0x1e, 0x11, 0x0f, 0x00, 0x00, 0x17, 0xff, 0xff, 0x13, 0x00, 0x00, + 0x31, 0xff, 0x31, 0x00, 0x00, 0x15, 0x69, 0x45, 0x0a, 0x00, 0xd4, 0xff, + 0x03, 0x00, 0x00, 0x15, 0xff, 0x8b, 0x00, 0x00, 0x35, 0xff, 0x57, 0x84, + 0x00, 0x02, 0x34, 0xff, 0x5b, 0x81, 0x00, 0x02, 0x55, 0xff, 0x4f, 0x88, + 0x00, 0x02, 0x71, 0xff, 0x45, 0x89, 0x00, 0x03, 0x23, 0xff, 0xff, 0x27, + 0x8d, 0x00, 0x03, 0x49, 0xff, 0xdd, 0x0a, 0x88, 0x00, 0x04, 0x5b, 0xff, + 0x68, 0xff, 0x2e, 0x8a, 0x00, 0x02, 0x59, 0xff, 0x34, 0xbf, 0x00, 0x03, + 0x02, 0x92, 0xff, 0x55, 0x84, 0x00, 0x02, 0x72, 0xff, 0x81, 0x83, 0x00, + 0x03, 0x06, 0xcd, 0xff, 0x44, 0x81, 0x00, 0x08, 0xb5, 0x95, 0x5c, 0x28, + 0x01, 0x00, 0x92, 0xff, 0x5c, 0x85, 0x00, 0x02, 0x69, 0xea, 0x99, 0x83, + 0x00, 0x03, 0x08, 0xff, 0xff, 0x42, 0x81, 0x00, 0x02, 0x32, 0x45, 0x2e, + 0x83, 0x00, 0x03, 0x09, 0xff, 0xff, 0x3e, 0x85, 0x00, 0x06, 0x17, 0xcd, + 0xa6, 0x0a, 0x63, 0xff, 0x89, 0x83, 0x00, 0x03, 0x2e, 0xff, 0xff, 0x03, + 0x8a, 0x00, 0x03, 0x13, 0xff, 0xff, 0x20, 0x92, 0x00, 0x03, 0x43, 0xff, + 0x98, 0x05, 0x82, 0x00, 0x02, 0x68, 0xff, 0x8c, 0x83, 0x00, 0x03, 0x0e, + 0xff, 0xff, 0x3a, 0x81, 0x00, 0x02, 0xaa, 0xff, 0x68, 0x83, 0x00, 0x03, + 0x1a, 0xff, 0xff, 0x29, 0x85, 0x00, 0x00, 0x1b, 0x80, 0xff, 0x8a, 0x00, + 0x00, 0x1b, 0x80, 0xff, 0x8b, 0x00, 0x07, 0x08, 0x3d, 0x98, 0xff, 0xff, + 0xb9, 0x50, 0x11, 0x80, 0x00, 0x00, 0x36, 0x8a, 0xff, 0x00, 0x17, 0x80, + 0x00, 0x07, 0x1d, 0x63, 0xd4, 0xff, 0xff, 0x7e, 0x2e, 0x03, 0x85, 0x00, + 0x03, 0x43, 0xff, 0xd4, 0x0a, 0x84, 0x00, 0x02, 0x9d, 0xff, 0x5e, 0x80, + 0x00, 0x0e, 0x32, 0xff, 0x38, 0x00, 0x11, 0xb7, 0xab, 0x3f, 0x5d, 0xb9, + 0x48, 0xff, 0x0e, 0x81, 0xaa, 0x83, 0x00, 0x06, 0x7e, 0xff, 0x4d, 0x00, + 0x65, 0xff, 0x61, 0x84, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, + 0x06, 0xff, 0xff, 0x4d, 0x81, 0x00, 0x03, 0x83, 0xff, 0xc7, 0x0b, 0x83, + 0x00, 0x03, 0x37, 0xcd, 0x68, 0x08, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x83, 0x00, 0x03, 0x1c, 0xff, 0xff, 0x5b, 0x81, 0x00, 0x02, 0x80, 0xff, + 0x8d, 0x8b, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x22, 0x8a, 0x00, 0x03, 0x8b, + 0xff, 0xbd, 0x07, 0x83, 0x00, 0x02, 0x30, 0x55, 0x27, 0x81, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, 0x86, 0x00, + 0x02, 0xb1, 0xff, 0x69, 0x8e, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x43, 0x82, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x80, 0x00, 0x03, 0x24, 0xdd, 0xff, 0x60, + 0x85, 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x05, 0x1d, 0xff, 0xb3, + 0x35, 0xff, 0x76, 0x80, 0x00, 0x05, 0x83, 0xff, 0x31, 0xff, 0xff, 0x04, + 0x80, 0x00, 0x05, 0x80, 0xff, 0x43, 0xa6, 0xff, 0x33, 0x81, 0x00, 0x02, + 0x80, 0xff, 0x53, 0x80, 0x00, 0x04, 0x03, 0xb1, 0xff, 0x96, 0x01, 0x82, + 0x00, 0x03, 0x0f, 0xd8, 0xff, 0x74, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x84, 0x00, 0x03, 0x3c, 0xff, 0xff, 0x1b, 0x80, 0x00, 0x03, 0x98, 0xff, + 0xaa, 0x03, 0x82, 0x00, 0x03, 0x15, 0xff, 0xff, 0x62, 0x81, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x25, 0x80, 0x00, + 0x02, 0xd8, 0xff, 0x53, 0x84, 0x00, 0x02, 0x42, 0x49, 0x2a, 0x86, 0x00, + 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, 0x03, 0x07, 0xff, 0xff, 0x4d, 0x84, + 0x00, 0x02, 0x7c, 0xff, 0x8d, 0x80, 0x00, 0x03, 0x11, 0xea, 0xff, 0x49, + 0x84, 0x00, 0x08, 0x70, 0xff, 0xaa, 0x02, 0x00, 0x23, 0xff, 0xff, 0x16, + 0x86, 0x00, 0x03, 0x31, 0xff, 0xff, 0x09, 0x80, 0x00, 0x09, 0x03, 0x89, + 0xff, 0x7c, 0x01, 0x00, 0x09, 0xab, 0xff, 0x5d, 0x84, 0x00, 0x03, 0x55, + 0xff, 0xca, 0x12, 0x80, 0x00, 0x03, 0x28, 0xff, 0xff, 0x32, 0x89, 0x00, + 0x04, 0x01, 0x70, 0xff, 0xb3, 0x10, 0x85, 0x00, 0x03, 0x34, 0xff, 0xff, + 0x07, 0x8a, 0x00, 0x02, 0x81, 0xff, 0x61, 0x8e, 0x00, 0x03, 0x26, 0xff, + 0xff, 0x15, 0x86, 0x00, 0x07, 0x0c, 0xd8, 0xa6, 0x02, 0x00, 0x18, 0xff, + 0x90, 0xa7, 0x00, 0x05, 0x39, 0xea, 0xff, 0xea, 0xaf, 0xab, 0x80, 0xff, + 0x00, 0x42, 0x83, 0x00, 0x0b, 0x40, 0xff, 0xd4, 0x1c, 0xbb, 0xff, 0xb1, + 0xc2, 0xff, 0xff, 0xcd, 0x21, 0x83, 0x00, 0x05, 0x0f, 0x8c, 0xff, 0xff, + 0xea, 0xbd, 0x80, 0xff, 0x01, 0xa3, 0x17, 0x83, 0x00, 0x0b, 0x37, 0xff, + 0xff, 0xe3, 0x95, 0x98, 0xea, 0xb3, 0x2d, 0xff, 0xff, 0x22, 0x82, 0x00, + 0x0a, 0x11, 0x92, 0xff, 0xff, 0xbd, 0x94, 0xc4, 0xff, 0xff, 0x80, 0x08, + 0x81, 0x00, 0x00, 0x0c, 0x80, 0xb9, 0x02, 0xcd, 0xff, 0xff, 0x83, 0xb9, + 0x00, 0x57, 0x82, 0x00, 0x0b, 0x31, 0xe3, 0xff, 0xff, 0xa0, 0xa0, 0xff, + 0x95, 0x14, 0xff, 0xff, 0x2d, 0x81, 0x00, 0x0b, 0x40, 0xff, 0xbf, 0x18, + 0xb3, 0xff, 0xb5, 0xd1, 0xff, 0xff, 0xd8, 0x25, 0x83, 0x00, 0x00, 0x57, + 0x80, 0xb9, 0x03, 0xc2, 0xff, 0xff, 0x17, 0x86, 0x00, 0x00, 0x4f, 0x82, + 0xb9, 0x02, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, 0x69, 0x81, + 0x00, 0x04, 0x19, 0xbf, 0xff, 0x62, 0x01, 0x86, 0x00, 0x03, 0x34, 0xff, + 0xff, 0x07, 0x84, 0x00, 0x0d, 0x55, 0xff, 0x46, 0xa6, 0xbf, 0xff, 0xff, + 0x72, 0x22, 0xea, 0xbb, 0xff, 0xff, 0x84, 0x81, 0x00, 0x0b, 0x44, 0xff, + 0x90, 0x18, 0xaf, 0xff, 0xb5, 0xd1, 0xff, 0xff, 0xe3, 0x2a, 0x83, 0x00, + 0x0a, 0x14, 0x9d, 0xff, 0xff, 0xad, 0x8f, 0xb7, 0xff, 0xff, 0x90, 0x0e, + 0x82, 0x00, 0x0b, 0x43, 0xff, 0xb5, 0x18, 0xb9, 0xff, 0xb1, 0xc2, 0xff, + 0xff, 0xcd, 0x21, 0x83, 0x00, 0x0b, 0x37, 0xff, 0xff, 0xe3, 0x95, 0x99, + 0xea, 0xab, 0x28, 0xff, 0xff, 0x25, 0x82, 0x00, 0x05, 0x31, 0xff, 0xca, + 0x02, 0x22, 0xd4, 0x82, 0xff, 0x00, 0x24, 0x82, 0x00, 0x0a, 0x14, 0xaa, + 0xff, 0xff, 0xaf, 0x94, 0xab, 0xff, 0xff, 0xa5, 0x12, 0x82, 0x00, 0x05, + 0x32, 0xb9, 0xbb, 0xff, 0xff, 0xc4, 0x82, 0xb9, 0x00, 0x1f, 0x82, 0x00, + 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x80, + 0x00, 0x03, 0x40, 0xff, 0xff, 0x22, 0x84, 0x00, 0x07, 0x43, 0xff, 0xff, + 0x1d, 0x00, 0x40, 0xff, 0xbb, 0x87, 0x00, 0x09, 0x11, 0xff, 0xff, 0x20, + 0x00, 0x00, 0x2e, 0xff, 0xff, 0x27, 0x82, 0x00, 0x03, 0x5b, 0xff, 0xb5, + 0x0e, 0x80, 0x00, 0x03, 0x3d, 0xff, 0xea, 0x12, 0x84, 0x00, 0x03, 0x28, + 0xff, 0xff, 0x20, 0x80, 0x00, 0x00, 0x33, 0x85, 0xa3, 0x03, 0xcd, 0xff, + 0xff, 0x0a, 0x85, 0x00, 0x03, 0x11, 0xff, 0xff, 0x1f, 0x8b, 0x00, 0x02, + 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x3d, 0xff, 0xb1, 0x96, 0x00, 0x03, + 0x43, 0xff, 0xd4, 0x0a, 0x84, 0x00, 0x02, 0x9d, 0xff, 0x5e, 0x97, 0x00, + 0x02, 0x85, 0xff, 0x59, 0x88, 0x00, 0x02, 0x74, 0xff, 0x2e, 0x80, 0x00, + 0x02, 0x59, 0xff, 0x45, 0x82, 0x00, 0x00, 0x50, 0x8a, 0xff, 0x0b, 0xaa, + 0x00, 0x00, 0x08, 0xff, 0xff, 0x30, 0x00, 0x00, 0x31, 0xff, 0x31, 0x84, + 0x00, 0x0c, 0x9d, 0xff, 0x15, 0x00, 0x00, 0x2a, 0xff, 0x6f, 0x00, 0x13, + 0xc4, 0x94, 0x05, 0x84, 0x00, 0x09, 0x1d, 0xff, 0x8a, 0x00, 0x00, 0x06, + 0x4d, 0xff, 0xa3, 0x0c, 0x88, 0x00, 0x02, 0x63, 0xff, 0x3a, 0x89, 0x00, + 0x03, 0x58, 0xff, 0xbf, 0x03, 0x8d, 0x00, 0x03, 0x18, 0xff, 0xff, 0x34, + 0x87, 0x00, 0x06, 0x32, 0xff, 0x5f, 0x03, 0x98, 0xbf, 0x12, 0x89, 0x00, + 0x02, 0x59, 0xff, 0x34, 0xbf, 0x00, 0x03, 0x39, 0xff, 0xbb, 0x0a, 0x83, + 0x00, 0x03, 0x01, 0xc2, 0xff, 0x45, 0x84, 0x00, 0x02, 0x77, 0xff, 0x73, + 0x87, 0x00, 0x02, 0x92, 0xff, 0x5c, 0x86, 0x00, 0x01, 0x02, 0x08, 0x83, + 0x00, 0x03, 0x0b, 0xff, 0xff, 0x3a, 0x8a, 0x00, 0x03, 0x35, 0xff, 0xea, + 0x17, 0x84, 0x00, 0x07, 0x05, 0x90, 0xe3, 0x21, 0x00, 0x63, 0xff, 0x89, + 0x83, 0x00, 0x02, 0x39, 0xff, 0xc2, 0x8b, 0x00, 0x02, 0x42, 0xff, 0xa0, + 0x92, 0x00, 0x03, 0x17, 0xd4, 0xff, 0x20, 0x83, 0x00, 0x03, 0x40, 0xff, + 0xc7, 0x0b, 0x82, 0x00, 0x03, 0x24, 0xff, 0xff, 0x1a, 0x80, 0x00, 0x03, + 0x04, 0xff, 0xff, 0x41, 0x84, 0x00, 0x02, 0xb3, 0xff, 0x4f, 0x85, 0x00, + 0x00, 0x1b, 0x80, 0xff, 0x8a, 0x00, 0x00, 0x1b, 0x80, 0xff, 0x89, 0x00, + 0x07, 0x18, 0x5a, 0xc7, 0xff, 0xff, 0x8f, 0x37, 0x05, 0x82, 0x00, 0x00, + 0x36, 0x8a, 0xff, 0x00, 0x17, 0x82, 0x00, 0x07, 0x0c, 0x47, 0xaa, 0xff, + 0xff, 0xab, 0x49, 0x0e, 0x83, 0x00, 0x02, 0x2b, 0x45, 0x38, 0x85, 0x00, + 0x02, 0xa0, 0xff, 0x58, 0x80, 0x00, 0x0f, 0x6b, 0xff, 0x0c, 0x00, 0x82, + 0xc7, 0x14, 0x00, 0x00, 0x74, 0xbf, 0xad, 0x00, 0x55, 0xff, 0x0a, 0x81, + 0x00, 0x08, 0x14, 0xff, 0xff, 0x1a, 0x00, 0x2a, 0xff, 0xca, 0x07, 0x83, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x25, 0xff, 0xff, 0x25, + 0x80, 0x00, 0x03, 0x0a, 0xff, 0xff, 0x68, 0x84, 0x00, 0x01, 0x03, 0x07, + 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x79, 0xff, 0xb9, + 0x01, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8b, 0x00, 0x03, 0x2d, 0xff, + 0xff, 0x22, 0x89, 0x00, 0x03, 0x0c, 0xff, 0xff, 0x64, 0x8b, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, 0x86, 0x00, + 0x02, 0xb1, 0xff, 0x69, 0x8e, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x43, 0x82, + 0x00, 0x09, 0x80, 0xff, 0x8d, 0x00, 0x00, 0x18, 0xbf, 0xff, 0x71, 0x02, + 0x85, 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x0e, 0x1d, 0xff, 0xb9, + 0x0a, 0xdd, 0xea, 0x10, 0x00, 0x16, 0xff, 0x99, 0x17, 0xff, 0xff, 0x04, + 0x80, 0x00, 0x06, 0x80, 0xff, 0x47, 0x3e, 0xff, 0x95, 0x01, 0x80, 0x00, + 0x02, 0x80, 0xff, 0x53, 0x80, 0x00, 0x03, 0x1d, 0xff, 0xff, 0x4a, 0x84, + 0x00, 0x03, 0x79, 0xff, 0xdd, 0x04, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x84, 0x00, 0x09, 0x2e, 0xff, 0xff, 0x22, 0x00, 0x00, 0x16, 0xff, 0xff, + 0x55, 0x84, 0x00, 0x03, 0x8a, 0xff, 0xbf, 0x01, 0x80, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x84, 0x00, 0x03, 0x37, 0xff, 0xff, 0x21, 0x80, 0x00, 0x02, + 0xa0, 0xff, 0x6a, 0x90, 0x00, 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, 0x03, + 0x07, 0xff, 0xff, 0x4d, 0x84, 0x00, 0x02, 0x7c, 0xff, 0x8d, 0x81, 0x00, + 0x02, 0x78, 0xff, 0x9f, 0x83, 0x00, 0x09, 0x0b, 0xdd, 0xff, 0x4d, 0x00, + 0x00, 0x0e, 0xff, 0xff, 0x29, 0x80, 0x00, 0x02, 0x2e, 0x38, 0x24, 0x80, + 0x00, 0x02, 0x45, 0xff, 0xad, 0x82, 0x00, 0x08, 0x15, 0xcd, 0xff, 0x39, + 0x00, 0x5f, 0xff, 0x9f, 0x06, 0x84, 0x00, 0x09, 0x06, 0xa0, 0xff, 0x74, + 0x00, 0x00, 0x06, 0xa2, 0xff, 0x72, 0x8a, 0x00, 0x03, 0x4b, 0xff, 0xdd, + 0x22, 0x86, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x8a, 0x00, 0x03, 0x1d, + 0xff, 0xea, 0x1b, 0x8d, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x86, 0x00, + 0x02, 0x45, 0xff, 0x47, 0x80, 0x00, 0x02, 0x81, 0xff, 0x20, 0xa5, 0x00, + 0x0b, 0x0f, 0xd8, 0xff, 0x7b, 0x0f, 0x00, 0x00, 0x0e, 0x72, 0xff, 0xea, + 0x15, 0x82, 0x00, 0x0c, 0x40, 0xff, 0xca, 0x95, 0x6a, 0x0f, 0x00, 0x00, + 0x26, 0xb7, 0xff, 0xa2, 0x04, 0x81, 0x00, 0x0c, 0x04, 0x91, 0xff, 0xad, + 0x2e, 0x05, 0x00, 0x05, 0x31, 0xb5, 0xff, 0xa5, 0x07, 0x81, 0x00, 0x0c, + 0x10, 0xd1, 0xff, 0x81, 0x0f, 0x00, 0x00, 0x0c, 0x6d, 0xaa, 0xff, 0xff, + 0x22, 0x81, 0x00, 0x04, 0x04, 0x91, 0xff, 0xa2, 0x23, 0x80, 0x00, 0x03, + 0x2a, 0xbb, 0xff, 0x70, 0x85, 0x00, 0x02, 0x4b, 0xff, 0xb9, 0x88, 0x00, + 0x0c, 0x0c, 0xca, 0xff, 0x8f, 0x14, 0x00, 0x00, 0x18, 0x92, 0x80, 0xff, + 0xff, 0x2a, 0x81, 0x00, 0x0b, 0x40, 0xff, 0xb1, 0x92, 0x73, 0x14, 0x00, + 0x01, 0x24, 0xbd, 0xff, 0x98, 0x87, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, + 0x8b, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, + 0x69, 0x80, 0x00, 0x04, 0x10, 0xab, 0xff, 0x6f, 0x02, 0x87, 0x00, 0x03, + 0x34, 0xff, 0xff, 0x07, 0x84, 0x00, 0x0e, 0x52, 0xff, 0xa0, 0x6c, 0x02, + 0x1f, 0xff, 0xdd, 0x8b, 0x3d, 0x00, 0x3c, 0xff, 0xff, 0x0f, 0x80, 0x00, + 0x0c, 0x41, 0xff, 0xa5, 0x92, 0x73, 0x14, 0x00, 0x01, 0x24, 0xbd, 0xff, + 0x9f, 0x01, 0x81, 0x00, 0x0c, 0x07, 0x9d, 0xff, 0xa5, 0x1f, 0x00, 0x00, + 0x01, 0x2a, 0xbf, 0xff, 0x82, 0x01, 0x81, 0x00, 0x0c, 0x41, 0xff, 0xd4, + 0x8b, 0x69, 0x0f, 0x00, 0x00, 0x23, 0xaf, 0xff, 0xa8, 0x04, 0x81, 0x00, + 0x0c, 0x10, 0xd1, 0xff, 0x80, 0x0e, 0x00, 0x00, 0x0d, 0x71, 0xa6, 0xff, + 0xff, 0x24, 0x82, 0x00, 0x0b, 0x1a, 0xff, 0xff, 0x1d, 0xb7, 0xea, 0x64, + 0x2e, 0x22, 0x27, 0x36, 0x11, 0x82, 0x00, 0x03, 0x7a, 0xff, 0x81, 0x13, + 0x80, 0x00, 0x03, 0x14, 0x7f, 0xff, 0x7d, 0x84, 0x00, 0x03, 0x0d, 0xff, + 0xff, 0x2f, 0x88, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, + 0xff, 0xff, 0x2d, 0x80, 0x00, 0x03, 0x0b, 0xd8, 0xff, 0x5f, 0x84, 0x00, + 0x08, 0x99, 0xff, 0x8d, 0x00, 0x00, 0x26, 0xff, 0xff, 0x0b, 0x86, 0x00, + 0x03, 0x26, 0xff, 0xff, 0x0a, 0x80, 0x00, 0x03, 0x5a, 0xff, 0xad, 0x0b, + 0x80, 0x00, 0x03, 0x29, 0xff, 0xff, 0x27, 0x81, 0x00, 0x03, 0x07, 0xc4, + 0xff, 0x50, 0x84, 0x00, 0x02, 0x6e, 0xff, 0x90, 0x89, 0x00, 0x03, 0x1a, + 0xca, 0xff, 0x50, 0x86, 0x00, 0x03, 0x11, 0xff, 0xff, 0x1f, 0x8b, 0x00, + 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x3d, 0xff, 0xb1, 0x96, 0x00, + 0x02, 0x2b, 0x45, 0x38, 0x85, 0x00, 0x02, 0xa0, 0xff, 0x58, 0x97, 0x00, + 0x02, 0x7e, 0xff, 0x54, 0x88, 0x00, 0x02, 0x41, 0x6d, 0x1a, 0x80, 0x00, + 0x02, 0x33, 0x6d, 0x28, 0x82, 0x00, 0x05, 0x17, 0x2a, 0x2a, 0x4e, 0xff, + 0x3f, 0x81, 0x2a, 0x04, 0xaa, 0x7b, 0x2a, 0x2a, 0x26, 0x80, 0x00, 0x07, + 0x6e, 0xff, 0xbf, 0x30, 0x02, 0x31, 0xff, 0x31, 0x84, 0x00, 0x0b, 0x53, + 0xff, 0x6a, 0x0a, 0x0e, 0x85, 0xff, 0x36, 0x02, 0x84, 0xd4, 0x19, 0x85, + 0x00, 0x08, 0x02, 0xab, 0xff, 0x2b, 0x49, 0xb3, 0xff, 0x72, 0x0e, 0x89, + 0x00, 0x02, 0x38, 0x6d, 0x22, 0x89, 0x00, 0x02, 0x95, 0xff, 0x72, 0x8f, + 0x00, 0x02, 0xb5, 0xff, 0x5e, 0x86, 0x00, 0x07, 0x0f, 0xc7, 0xb9, 0x0b, + 0x00, 0x26, 0xff, 0x83, 0x89, 0x00, 0x02, 0x59, 0xff, 0x34, 0xbe, 0x00, + 0x03, 0x07, 0xb1, 0xff, 0x40, 0x84, 0x00, 0x05, 0x11, 0xff, 0xff, 0x2b, + 0x00, 0x0a, 0x80, 0x34, 0x04, 0x00, 0x00, 0x54, 0xff, 0xaf, 0x87, 0x00, + 0x02, 0x92, 0xff, 0x5c, 0x8e, 0x00, 0x03, 0x38, 0xff, 0xff, 0x15, 0x87, + 0x00, 0x05, 0x08, 0x1d, 0x57, 0xea, 0xff, 0x43, 0x85, 0x00, 0x07, 0x58, + 0xff, 0x49, 0x00, 0x00, 0x63, 0xff, 0x89, 0x83, 0x00, 0x0a, 0x44, 0xff, + 0x9f, 0x18, 0x5c, 0x9f, 0xd1, 0xbb, 0x84, 0x43, 0x08, 0x83, 0x00, 0x0a, + 0x68, 0xff, 0x67, 0x00, 0x30, 0x79, 0xb1, 0xcd, 0x96, 0x52, 0x0f, 0x8a, + 0x00, 0x02, 0x7b, 0xff, 0x66, 0x84, 0x00, 0x04, 0x06, 0x96, 0xff, 0x79, + 0x13, 0x80, 0x00, 0x03, 0x1f, 0x9c, 0xff, 0x60, 0x81, 0x00, 0x03, 0x04, + 0xff, 0xff, 0x48, 0x84, 0x00, 0x02, 0x90, 0xff, 0x71, 0x85, 0x00, 0x00, + 0x1b, 0x80, 0xff, 0x8a, 0x00, 0x00, 0x1b, 0x80, 0xff, 0x86, 0x00, 0x07, + 0x03, 0x2e, 0x7f, 0xff, 0xff, 0xdd, 0x68, 0x20, 0x86, 0x00, 0x8a, 0x02, + 0x85, 0x00, 0x07, 0x03, 0x2e, 0x80, 0xff, 0xff, 0xdd, 0x68, 0x22, 0x8b, + 0x00, 0x03, 0x24, 0xff, 0xff, 0x2b, 0x80, 0x00, 0x05, 0xb3, 0x8d, 0x00, + 0x23, 0xff, 0x4d, 0x80, 0x00, 0x06, 0x42, 0xff, 0x71, 0x00, 0x3e, 0xff, + 0x16, 0x81, 0x00, 0x08, 0x4d, 0xff, 0x94, 0x00, 0x00, 0x04, 0xbd, 0xff, + 0x37, 0x83, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x80, 0x00, 0x05, 0x03, 0x10, + 0x38, 0xb3, 0xff, 0x63, 0x81, 0x00, 0x03, 0x22, 0xff, 0xff, 0x41, 0x8b, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x43, 0xff, 0xff, 0x16, + 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8b, 0x00, 0x03, 0x2d, 0xff, 0xff, + 0x22, 0x89, 0x00, 0x03, 0x23, 0xff, 0xff, 0x3f, 0x8b, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, 0x86, 0x00, 0x02, + 0xb1, 0xff, 0x69, 0x8e, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x43, 0x82, 0x00, + 0x08, 0x80, 0xff, 0x8d, 0x00, 0x0e, 0xa5, 0xff, 0x83, 0x06, 0x86, 0x00, + 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x0e, 0x1d, 0xff, 0xbf, 0x00, 0x6f, + 0xff, 0x47, 0x00, 0x50, 0xff, 0x47, 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, + 0x06, 0x80, 0xff, 0x4d, 0x06, 0xb7, 0xff, 0x2b, 0x80, 0x00, 0x02, 0x80, + 0xff, 0x53, 0x80, 0x00, 0x03, 0x39, 0xff, 0xff, 0x29, 0x84, 0x00, 0x03, + 0x4d, 0xff, 0xff, 0x1a, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, + 0x09, 0x48, 0xff, 0xff, 0x12, 0x00, 0x00, 0x30, 0xff, 0xff, 0x30, 0x84, + 0x00, 0x03, 0x55, 0xff, 0xff, 0x12, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x83, 0x00, 0x04, 0x01, 0x76, 0xff, 0xc7, 0x06, 0x80, 0x00, 0x04, 0x53, + 0xff, 0xff, 0x44, 0x06, 0x8e, 0x00, 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, + 0x03, 0x07, 0xff, 0xff, 0x4d, 0x84, 0x00, 0x02, 0x7c, 0xff, 0x8d, 0x81, + 0x00, 0x03, 0x30, 0xff, 0xff, 0x1f, 0x82, 0x00, 0x03, 0x3c, 0xff, 0xff, + 0x14, 0x80, 0x00, 0x08, 0xc2, 0xff, 0x3d, 0x00, 0x00, 0x06, 0xd8, 0xff, + 0x99, 0x80, 0x00, 0x02, 0x5d, 0xff, 0x79, 0x83, 0x00, 0x06, 0x3d, 0xff, + 0xbf, 0x37, 0xff, 0xea, 0x1f, 0x86, 0x00, 0x08, 0x25, 0xff, 0xff, 0x30, + 0x00, 0x50, 0xff, 0xc2, 0x10, 0x89, 0x00, 0x03, 0x2c, 0xff, 0xff, 0x3e, + 0x87, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x8b, 0x00, 0x02, 0x66, 0xff, + 0x7d, 0x8d, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x85, 0x00, 0x03, 0x02, + 0xa5, 0xe3, 0x0f, 0x80, 0x00, 0x02, 0x32, 0xff, 0x65, 0xa5, 0x00, 0x03, + 0x3a, 0xff, 0xff, 0x16, 0x81, 0x00, 0x03, 0x0a, 0xe3, 0xff, 0x46, 0x82, + 0x00, 0x04, 0x40, 0xff, 0xff, 0x8f, 0x02, 0x81, 0x00, 0x03, 0x30, 0xff, + 0xff, 0x2d, 0x81, 0x00, 0x03, 0x3d, 0xff, 0xea, 0x1b, 0x82, 0x00, 0x03, + 0x27, 0xff, 0xff, 0x40, 0x81, 0x00, 0x03, 0x4c, 0xff, 0xd8, 0x10, 0x81, + 0x00, 0x04, 0x04, 0xa0, 0xff, 0xff, 0x22, 0x81, 0x00, 0x03, 0x3b, 0xff, + 0xd4, 0x15, 0x82, 0x00, 0x03, 0x2b, 0xff, 0xff, 0x20, 0x84, 0x00, 0x02, + 0x4b, 0xff, 0xb9, 0x88, 0x00, 0x03, 0x43, 0xff, 0xea, 0x16, 0x81, 0x00, + 0x04, 0x10, 0xc7, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x04, 0x40, 0xff, 0xff, + 0x84, 0x02, 0x81, 0x00, 0x03, 0x41, 0xff, 0xff, 0x14, 0x86, 0x00, 0x03, + 0x24, 0xff, 0xff, 0x17, 0x8b, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, + 0x00, 0x09, 0x7c, 0xff, 0x69, 0x00, 0x00, 0x0a, 0x95, 0xff, 0x7c, 0x05, + 0x88, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x84, 0x00, 0x0e, 0x50, 0xff, + 0xff, 0x17, 0x00, 0x00, 0xa3, 0xff, 0xaa, 0x01, 0x00, 0x09, 0xff, 0xff, + 0x24, 0x80, 0x00, 0x04, 0x40, 0xff, 0xff, 0x84, 0x02, 0x81, 0x00, 0x03, + 0x41, 0xff, 0xff, 0x15, 0x81, 0x00, 0x03, 0x43, 0xff, 0xff, 0x1b, 0x82, + 0x00, 0x03, 0x33, 0xff, 0xff, 0x29, 0x81, 0x00, 0x04, 0x40, 0xff, 0xff, + 0x91, 0x02, 0x81, 0x00, 0x03, 0x2a, 0xff, 0xff, 0x30, 0x81, 0x00, 0x03, + 0x4b, 0xff, 0xd8, 0x0e, 0x81, 0x00, 0x04, 0x06, 0xa6, 0xff, 0xff, 0x24, + 0x82, 0x00, 0x05, 0x0b, 0xff, 0xff, 0x87, 0xca, 0x25, 0x87, 0x00, 0x03, + 0x06, 0xff, 0xff, 0x20, 0x82, 0x00, 0x03, 0x15, 0x6f, 0x56, 0x04, 0x83, + 0x00, 0x03, 0x0d, 0xff, 0xff, 0x2f, 0x88, 0x00, 0x02, 0x40, 0xff, 0xdd, + 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x81, 0x00, 0x03, 0x68, 0xff, + 0xc4, 0x06, 0x82, 0x00, 0x09, 0x20, 0xff, 0xff, 0x39, 0x00, 0x00, 0x10, + 0xff, 0xff, 0x1f, 0x86, 0x00, 0x02, 0x3f, 0xff, 0xaa, 0x81, 0x00, 0x09, + 0x05, 0x8f, 0xff, 0x6e, 0x00, 0x00, 0x0b, 0xaf, 0xff, 0x4f, 0x83, 0x00, + 0x03, 0x56, 0xff, 0xb7, 0x04, 0x82, 0x00, 0x03, 0x0e, 0xe3, 0xff, 0x39, + 0x88, 0x00, 0x04, 0x0c, 0xa6, 0xff, 0x6f, 0x01, 0x86, 0x00, 0x03, 0x11, + 0xff, 0xff, 0x1f, 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, + 0x3d, 0xff, 0xb1, 0x86, 0x00, 0x06, 0x16, 0x5f, 0x90, 0x92, 0x6b, 0x38, + 0x0a, 0x82, 0x00, 0x01, 0x04, 0x0d, 0x89, 0x00, 0x03, 0x24, 0xff, 0xff, + 0x2b, 0x97, 0x00, 0x02, 0x78, 0xff, 0x50, 0x99, 0x00, 0x02, 0x46, 0xdd, + 0x05, 0x80, 0x00, 0x02, 0x06, 0xe3, 0x41, 0x83, 0x00, 0x08, 0x0e, 0x95, + 0xff, 0xff, 0xb5, 0x8b, 0xff, 0x52, 0x0e, 0x83, 0x00, 0x01, 0x08, 0x8a, + 0x81, 0xff, 0x04, 0x6c, 0x02, 0x49, 0xff, 0x40, 0x87, 0x00, 0x00, 0x5c, + 0x80, 0xff, 0x01, 0x7f, 0x26, 0x99, 0x00, 0x03, 0x06, 0xff, 0xff, 0x49, + 0x8f, 0x00, 0x02, 0x71, 0xff, 0x8d, 0x87, 0x00, 0x01, 0x26, 0x2f, 0x80, + 0x00, 0x01, 0x48, 0x15, 0x89, 0x00, 0x02, 0x59, 0xff, 0x34, 0xbe, 0x00, + 0x03, 0x4d, 0xff, 0x9f, 0x04, 0x84, 0x00, 0x05, 0x1b, 0xff, 0xff, 0x1e, + 0x00, 0x1b, 0x80, 0xff, 0x04, 0x00, 0x00, 0x41, 0xff, 0xe3, 0x87, 0x00, + 0x02, 0x92, 0xff, 0x5c, 0x8d, 0x00, 0x03, 0x12, 0xbb, 0xff, 0x64, 0x86, + 0x00, 0x00, 0x5c, 0x80, 0xff, 0x02, 0xc4, 0x6f, 0x21, 0x85, 0x00, 0x08, + 0x29, 0xff, 0x7f, 0x02, 0x00, 0x00, 0x63, 0xff, 0x89, 0x83, 0x00, 0x03, + 0x50, 0xff, 0xd1, 0xe3, 0x83, 0xff, 0x01, 0xa8, 0x1c, 0x82, 0x00, 0x0b, + 0x8d, 0xff, 0x52, 0x65, 0xff, 0xff, 0xb3, 0xcd, 0xff, 0xff, 0xc2, 0x25, + 0x88, 0x00, 0x03, 0x2b, 0xff, 0xd8, 0x11, 0x85, 0x00, 0x0a, 0x09, 0x5f, + 0xc7, 0xff, 0xab, 0x98, 0xb9, 0xff, 0xa5, 0x44, 0x01, 0x82, 0x00, 0x02, + 0xa6, 0xff, 0x6d, 0x83, 0x00, 0x03, 0x03, 0xbb, 0xff, 0x84, 0x85, 0x00, + 0x00, 0x02, 0x80, 0x09, 0x8a, 0x00, 0x00, 0x02, 0x80, 0x09, 0x85, 0x00, + 0x06, 0x21, 0xad, 0xff, 0xff, 0xb1, 0x4b, 0x0f, 0xa0, 0x00, 0x06, 0x1a, + 0x5e, 0xcd, 0xff, 0xff, 0x92, 0x0d, 0x88, 0x00, 0x03, 0x17, 0xaa, 0xff, + 0x79, 0x80, 0x00, 0x06, 0x0b, 0xff, 0x61, 0x00, 0x62, 0xff, 0x16, 0x80, + 0x00, 0x06, 0x39, 0xff, 0x4b, 0x00, 0x36, 0xff, 0x1d, 0x80, 0x00, 0x03, + 0x02, 0xab, 0xff, 0x44, 0x80, 0x00, 0x02, 0x5d, 0xff, 0x83, 0x83, 0x00, + 0x00, 0x80, 0x85, 0xff, 0x01, 0x7d, 0x34, 0x82, 0x00, 0x03, 0x32, 0xff, + 0xff, 0x2e, 0x8b, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x2a, + 0xff, 0xff, 0x24, 0x80, 0x00, 0x02, 0x80, 0xff, 0x92, 0x85, 0x0b, 0x00, + 0x0a, 0x82, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x22, 0x89, 0x00, 0x03, 0x32, + 0xff, 0xff, 0x2e, 0x8b, 0x00, 0x00, 0x80, 0x88, 0xff, 0x00, 0x53, 0x86, + 0x00, 0x02, 0xb1, 0xff, 0x69, 0x8e, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x43, + 0x82, 0x00, 0x07, 0x80, 0xff, 0x8d, 0x06, 0x8c, 0xff, 0xc7, 0x0b, 0x87, + 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x0e, 0x1d, 0xff, 0xc2, 0x00, + 0x2a, 0xff, 0x95, 0x00, 0xa6, 0xea, 0x10, 0x17, 0xff, 0xff, 0x04, 0x80, + 0x00, 0x06, 0x80, 0xff, 0x4d, 0x00, 0x48, 0xff, 0x88, 0x80, 0x00, 0x02, + 0x80, 0xff, 0x53, 0x80, 0x00, 0x03, 0x4b, 0xff, 0xff, 0x19, 0x84, 0x00, + 0x03, 0x39, 0xff, 0xff, 0x28, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, + 0x00, 0x03, 0x0e, 0xb1, 0xff, 0x91, 0x80, 0x00, 0x03, 0x47, 0xff, 0xff, + 0x1d, 0x84, 0x00, 0x03, 0x3e, 0xff, 0xff, 0x24, 0x80, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x81, 0x00, 0x05, 0x06, 0x20, 0x70, 0xff, 0xff, 0x47, 0x81, + 0x00, 0x07, 0x08, 0x82, 0xff, 0xff, 0xc2, 0x64, 0x38, 0x16, 0x8b, 0x00, + 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, 0x03, 0x07, 0xff, 0xff, 0x4d, 0x84, + 0x00, 0x02, 0x7c, 0xff, 0x8d, 0x81, 0x00, 0x03, 0x05, 0xbb, 0xff, 0x5a, + 0x82, 0x00, 0x02, 0x85, 0xff, 0x7f, 0x81, 0x00, 0x05, 0x84, 0xff, 0x55, + 0x00, 0x00, 0x29, 0x80, 0xff, 0x05, 0x12, 0x00, 0x00, 0x79, 0xff, 0x56, + 0x83, 0x00, 0x01, 0x01, 0x78, 0x80, 0xff, 0x00, 0x4e, 0x88, 0x00, 0x06, + 0x60, 0xff, 0xad, 0x22, 0xdd, 0xff, 0x3b, 0x89, 0x00, 0x03, 0x16, 0xc4, + 0xff, 0x63, 0x88, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x8b, 0x00, 0x03, + 0x11, 0xd1, 0xff, 0x2b, 0x8c, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x85, + 0x00, 0x02, 0x2a, 0xff, 0x6e, 0x81, 0x00, 0x03, 0x04, 0xb7, 0xd8, 0x0c, + 0xa5, 0x00, 0x01, 0x04, 0x10, 0x83, 0x00, 0x02, 0x98, 0xff, 0x5f, 0x82, + 0x00, 0x03, 0x40, 0xff, 0xff, 0x36, 0x82, 0x00, 0x03, 0x02, 0xbf, 0xff, + 0x5b, 0x81, 0x00, 0x02, 0x89, 0xff, 0x75, 0x83, 0x00, 0x03, 0x01, 0x43, + 0x3a, 0x20, 0x81, 0x00, 0x02, 0x89, 0xff, 0x79, 0x83, 0x00, 0x03, 0x49, + 0xff, 0xff, 0x22, 0x81, 0x00, 0x02, 0x84, 0xff, 0x68, 0x84, 0x00, 0x02, + 0x9f, 0xff, 0x55, 0x84, 0x00, 0x02, 0x4b, 0xff, 0xb9, 0x88, 0x00, 0x02, + 0x7a, 0xff, 0x88, 0x83, 0x00, 0x03, 0x59, 0xff, 0xff, 0x2a, 0x81, 0x00, + 0x03, 0x40, 0xff, 0xff, 0x28, 0x82, 0x00, 0x03, 0x1a, 0xff, 0xff, 0x26, + 0x86, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, 0x8b, 0x00, 0x03, 0x04, 0xff, + 0xff, 0x3b, 0x85, 0x00, 0x08, 0x7c, 0xff, 0x69, 0x00, 0x05, 0x81, 0xff, + 0x89, 0x07, 0x89, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x84, 0x00, 0x02, + 0x50, 0xff, 0xb3, 0x80, 0x00, 0x02, 0x7e, 0xff, 0x6b, 0x80, 0x00, 0x02, + 0xc7, 0xff, 0x2d, 0x80, 0x00, 0x03, 0x40, 0xff, 0xff, 0x28, 0x82, 0x00, + 0x03, 0x1a, 0xff, 0xff, 0x26, 0x81, 0x00, 0x02, 0x91, 0xff, 0x7e, 0x83, + 0x00, 0x03, 0x03, 0xb7, 0xff, 0x60, 0x81, 0x00, 0x03, 0x40, 0xff, 0xff, + 0x39, 0x82, 0x00, 0x03, 0x01, 0xb9, 0xff, 0x5c, 0x81, 0x00, 0x02, 0x88, + 0xff, 0x75, 0x83, 0x00, 0x03, 0x4d, 0xff, 0xff, 0x24, 0x82, 0x00, 0x00, + 0x03, 0x80, 0xff, 0x00, 0x3c, 0x88, 0x00, 0x03, 0x0a, 0xff, 0xff, 0x2a, + 0x8c, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x2f, 0x88, 0x00, 0x02, 0x40, 0xff, + 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x81, 0x00, 0x03, 0x24, + 0xff, 0xff, 0x34, 0x82, 0x00, 0x03, 0x5f, 0xff, 0xc4, 0x07, 0x80, 0x00, + 0x08, 0xc4, 0xff, 0x35, 0x00, 0x00, 0x08, 0xa5, 0xaa, 0x7e, 0x80, 0x00, + 0x02, 0x5c, 0xff, 0x74, 0x82, 0x00, 0x08, 0x15, 0xc4, 0xff, 0x37, 0x00, + 0x6d, 0xff, 0x81, 0x02, 0x83, 0x00, 0x03, 0x14, 0xff, 0xff, 0x33, 0x82, + 0x00, 0x03, 0x45, 0xff, 0xc2, 0x06, 0x87, 0x00, 0x04, 0x04, 0x83, 0xff, + 0x91, 0x07, 0x87, 0x00, 0x03, 0x19, 0xff, 0xff, 0x1c, 0x8b, 0x00, 0x02, + 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x03, 0x3a, 0xff, 0xcd, 0x01, 0x84, 0x00, + 0x01, 0x2e, 0xd8, 0x82, 0xff, 0x07, 0xcd, 0x60, 0x24, 0x06, 0x06, 0x29, + 0x8c, 0x28, 0x88, 0x00, 0x03, 0x17, 0xaa, 0xff, 0x79, 0x98, 0x00, 0x02, + 0x71, 0xff, 0x4b, 0x99, 0x00, 0x01, 0x6f, 0x8b, 0x81, 0x00, 0x02, 0x1e, + 0xff, 0x23, 0x84, 0x00, 0x02, 0x06, 0x47, 0xa6, 0x82, 0xff, 0x02, 0x89, + 0x3c, 0x04, 0x81, 0x00, 0x0c, 0x02, 0x27, 0x40, 0x3d, 0x20, 0x00, 0x1e, + 0xe3, 0x78, 0x01, 0x00, 0x09, 0x07, 0x82, 0x00, 0x01, 0x0a, 0x6e, 0x80, + 0xff, 0x00, 0x3c, 0x81, 0x00, 0x02, 0x2d, 0x5f, 0x1f, 0x94, 0x00, 0x03, + 0x17, 0xff, 0xff, 0x33, 0x8f, 0x00, 0x02, 0x55, 0xff, 0xbf, 0x94, 0x00, + 0x00, 0x35, 0x82, 0xdd, 0x02, 0xea, 0xff, 0xe3, 0x82, 0xdd, 0x00, 0x17, + 0xb7, 0x00, 0x03, 0x10, 0xd1, 0xff, 0x2e, 0x85, 0x00, 0x05, 0x22, 0xff, + 0xff, 0x19, 0x00, 0x1b, 0x80, 0xff, 0x05, 0x00, 0x00, 0x3c, 0xff, 0xff, + 0x06, 0x86, 0x00, 0x02, 0x92, 0xff, 0x5c, 0x8c, 0x00, 0x04, 0x12, 0x9f, + 0xff, 0x98, 0x09, 0x86, 0x00, 0x00, 0x5c, 0x80, 0xff, 0x02, 0xbd, 0x75, + 0x2d, 0x84, 0x00, 0x03, 0x0e, 0xb5, 0xb9, 0x0f, 0x80, 0x00, 0x02, 0x63, + 0xff, 0x89, 0x83, 0x00, 0x0c, 0x5d, 0xff, 0xff, 0x81, 0x28, 0x09, 0x03, + 0x13, 0x49, 0xd4, 0xff, 0xb5, 0x0d, 0x81, 0x00, 0x0c, 0xa2, 0xff, 0xaa, + 0xd4, 0x46, 0x09, 0x00, 0x03, 0x30, 0xb7, 0xff, 0xc2, 0x10, 0x86, 0x00, + 0x03, 0x01, 0x90, 0xff, 0x5e, 0x86, 0x00, 0x02, 0x03, 0x3d, 0x91, 0x82, + 0xff, 0x01, 0x7a, 0x32, 0x83, 0x00, 0x03, 0x57, 0xff, 0xea, 0x1a, 0x82, + 0x00, 0x03, 0x4d, 0xff, 0xff, 0x92, 0xa2, 0x00, 0x04, 0x36, 0xff, 0x9d, + 0x32, 0x04, 0xa4, 0x00, 0x04, 0x0a, 0x43, 0xc4, 0xff, 0x17, 0x87, 0x00, + 0x04, 0x36, 0xc2, 0xff, 0x78, 0x07, 0x80, 0x00, 0x05, 0x1e, 0xff, 0x44, + 0x00, 0xa8, 0xb1, 0x81, 0x00, 0x06, 0x47, 0xff, 0x2b, 0x00, 0x37, 0xff, + 0x1b, 0x80, 0x00, 0x03, 0x29, 0xff, 0xff, 0x10, 0x80, 0x00, 0x03, 0x24, + 0xff, 0xff, 0x15, 0x82, 0x00, 0x00, 0x80, 0x85, 0xff, 0x02, 0xc4, 0x6f, + 0x22, 0x81, 0x00, 0x03, 0x3a, 0xff, 0xff, 0x28, 0x8b, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x84, 0x00, 0x03, 0x22, 0xff, 0xff, 0x2d, 0x80, 0x00, 0x00, + 0x80, 0x87, 0xff, 0x00, 0xc2, 0x82, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x32, + 0x85, 0x13, 0x00, 0x09, 0x80, 0x00, 0x03, 0x3a, 0xff, 0xff, 0x28, 0x80, + 0x00, 0x00, 0x45, 0x83, 0xff, 0x00, 0x06, 0x80, 0x00, 0x00, 0x80, 0x88, + 0xff, 0x00, 0x53, 0x86, 0x00, 0x02, 0xb1, 0xff, 0x69, 0x8e, 0x00, 0x03, + 0x0d, 0xff, 0xff, 0x43, 0x82, 0x00, 0x03, 0x80, 0xff, 0x92, 0x72, 0x80, + 0xff, 0x00, 0x45, 0x87, 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x0e, + 0x1d, 0xff, 0xc2, 0x00, 0x02, 0xab, 0xff, 0x30, 0xff, 0x76, 0x00, 0x17, + 0xff, 0xff, 0x04, 0x80, 0x00, 0x0c, 0x80, 0xff, 0x4d, 0x00, 0x0a, 0xc7, + 0xff, 0x25, 0x00, 0x00, 0x80, 0xff, 0x53, 0x80, 0x00, 0x03, 0x54, 0xff, + 0xff, 0x13, 0x84, 0x00, 0x03, 0x32, 0xff, 0xff, 0x30, 0x80, 0x00, 0x02, + 0x80, 0xff, 0x90, 0x80, 0x06, 0x06, 0x07, 0x14, 0x3c, 0xab, 0xff, 0xea, + 0x26, 0x80, 0x00, 0x03, 0x50, 0xff, 0xff, 0x15, 0x84, 0x00, 0x03, 0x35, + 0xff, 0xff, 0x2c, 0x80, 0x00, 0x00, 0x80, 0x86, 0xff, 0x02, 0xea, 0x4f, + 0x01, 0x82, 0x00, 0x02, 0x04, 0x3c, 0x96, 0x81, 0xff, 0x02, 0xaf, 0x59, + 0x1b, 0x88, 0x00, 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, 0x03, 0x07, 0xff, + 0xff, 0x4d, 0x84, 0x00, 0x02, 0x7c, 0xff, 0x8d, 0x82, 0x00, 0x03, 0x57, + 0xff, 0xbb, 0x04, 0x80, 0x00, 0x03, 0x14, 0xff, 0xff, 0x34, 0x81, 0x00, + 0x0e, 0x5f, 0xff, 0x70, 0x00, 0x00, 0x57, 0xff, 0x6f, 0xff, 0x3a, 0x00, + 0x00, 0xa0, 0xff, 0x3b, 0x84, 0x00, 0x04, 0x16, 0xff, 0xff, 0xb9, 0x04, + 0x88, 0x00, 0x06, 0x09, 0xad, 0xff, 0xdd, 0xff, 0x7f, 0x01, 0x88, 0x00, + 0x04, 0x08, 0x9a, 0xff, 0x8a, 0x05, 0x88, 0x00, 0x03, 0x34, 0xff, 0xff, + 0x07, 0x8c, 0x00, 0x03, 0x4f, 0xff, 0x9a, 0x03, 0x8b, 0x00, 0x03, 0x26, + 0xff, 0xff, 0x15, 0x85, 0x00, 0x02, 0x76, 0xff, 0x26, 0x82, 0x00, 0x02, + 0x51, 0xff, 0x45, 0xad, 0x00, 0x02, 0x89, 0xff, 0x66, 0x82, 0x00, 0x03, + 0x40, 0xff, 0xff, 0x14, 0x83, 0x00, 0x02, 0x7f, 0xff, 0x80, 0x80, 0x00, + 0x03, 0x06, 0xea, 0xff, 0x46, 0x8a, 0x00, 0x03, 0x01, 0xcd, 0xff, 0x51, + 0x83, 0x00, 0x03, 0x2a, 0xff, 0xff, 0x22, 0x80, 0x00, 0x03, 0x05, 0xe3, + 0xff, 0x44, 0x84, 0x00, 0x02, 0x63, 0xff, 0x81, 0x84, 0x00, 0x02, 0x4b, + 0xff, 0xb9, 0x88, 0x00, 0x02, 0xad, 0xff, 0x5c, 0x83, 0x00, 0x03, 0x2b, + 0xff, 0xff, 0x2a, 0x81, 0x00, 0x03, 0x40, 0xff, 0xff, 0x08, 0x82, 0x00, + 0x03, 0x10, 0xff, 0xff, 0x2c, 0x86, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, + 0x8b, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x07, 0x7c, 0xff, + 0x69, 0x02, 0x6e, 0xff, 0x95, 0x0b, 0x8a, 0x00, 0x03, 0x34, 0xff, 0xff, + 0x07, 0x84, 0x00, 0x02, 0x50, 0xff, 0x8c, 0x80, 0x00, 0x02, 0x75, 0xff, + 0x56, 0x80, 0x00, 0x02, 0xb3, 0xff, 0x31, 0x80, 0x00, 0x03, 0x40, 0xff, + 0xff, 0x08, 0x82, 0x00, 0x03, 0x10, 0xff, 0xff, 0x2c, 0x80, 0x00, 0x03, + 0x07, 0xea, 0xff, 0x4a, 0x84, 0x00, 0x02, 0x74, 0xff, 0x92, 0x81, 0x00, + 0x03, 0x40, 0xff, 0xff, 0x17, 0x83, 0x00, 0x02, 0x7c, 0xff, 0x80, 0x80, + 0x00, 0x03, 0x01, 0xca, 0xff, 0x4f, 0x83, 0x00, 0x03, 0x2b, 0xff, 0xff, + 0x24, 0x83, 0x00, 0x03, 0xdd, 0xff, 0xb1, 0x03, 0x89, 0x00, 0x04, 0x99, + 0xff, 0xc2, 0x3e, 0x0d, 0x8a, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x2f, 0x88, + 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, + 0x81, 0x00, 0x03, 0x01, 0x9f, 0xff, 0x7d, 0x81, 0x00, 0x03, 0x07, 0xc7, + 0xff, 0x5b, 0x81, 0x00, 0x0e, 0x84, 0xff, 0x4e, 0x00, 0x00, 0x30, 0xff, + 0xcd, 0xff, 0x11, 0x00, 0x00, 0x82, 0xff, 0x50, 0x83, 0x00, 0x06, 0x32, + 0xff, 0xc4, 0x4c, 0xff, 0xb7, 0x10, 0x85, 0x00, 0x02, 0x74, 0xff, 0x84, + 0x81, 0x00, 0x03, 0x01, 0xa0, 0xff, 0x57, 0x88, 0x00, 0x03, 0x62, 0xff, + 0xb5, 0x11, 0x88, 0x00, 0x03, 0x53, 0xff, 0xc4, 0x06, 0x8b, 0x00, 0x02, + 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x03, 0x1b, 0xff, 0xff, 0x2d, 0x84, 0x00, + 0x07, 0x48, 0x73, 0x1f, 0x05, 0x0b, 0x27, 0x64, 0xd1, 0x82, 0xff, 0x01, + 0xdd, 0x1c, 0x87, 0x00, 0x04, 0x36, 0xc2, 0xff, 0x78, 0x07, 0x98, 0x00, + 0x02, 0x6c, 0xff, 0x47, 0x99, 0x00, 0x01, 0xab, 0x5a, 0x81, 0x00, 0x02, + 0x3c, 0xff, 0x08, 0x86, 0x00, 0x09, 0x01, 0x1a, 0x5e, 0xff, 0xaa, 0xea, + 0xff, 0xff, 0xa0, 0x16, 0x85, 0x00, 0x13, 0x07, 0x9d, 0xb7, 0x0e, 0x41, + 0xaf, 0xff, 0xff, 0x9a, 0x2a, 0x00, 0x00, 0x0c, 0x94, 0xff, 0x76, 0x4d, + 0xff, 0x99, 0x05, 0x80, 0x00, 0x02, 0x5a, 0xff, 0x3e, 0x94, 0x00, 0x03, + 0x22, 0xff, 0xff, 0x25, 0x8f, 0x00, 0x03, 0x43, 0xff, 0xff, 0x04, 0x93, + 0x00, 0x00, 0x36, 0x8a, 0xff, 0x00, 0x17, 0x93, 0x00, 0x00, 0x0a, 0x84, + 0x17, 0x00, 0x05, 0x98, 0x00, 0x02, 0x66, 0xff, 0x82, 0x86, 0x00, 0x05, + 0x22, 0xff, 0xff, 0x19, 0x00, 0x1b, 0x80, 0xff, 0x05, 0x00, 0x00, 0x3c, + 0xff, 0xff, 0x06, 0x86, 0x00, 0x02, 0x92, 0xff, 0x5c, 0x8b, 0x00, 0x04, + 0x22, 0xb5, 0xff, 0x91, 0x0f, 0x87, 0x00, 0x08, 0x09, 0x0f, 0x1a, 0x31, + 0x70, 0xff, 0xff, 0x65, 0x01, 0x81, 0x00, 0x03, 0x01, 0x79, 0xff, 0x2b, + 0x81, 0x00, 0x02, 0x63, 0xff, 0x89, 0x83, 0x00, 0x03, 0x1e, 0x2f, 0x2a, + 0x01, 0x82, 0x00, 0x03, 0x29, 0xff, 0xff, 0x54, 0x81, 0x00, 0x03, 0xb1, + 0xff, 0xff, 0x34, 0x82, 0x00, 0x03, 0x18, 0xe3, 0xff, 0x52, 0x86, 0x00, + 0x03, 0x2b, 0xff, 0xff, 0x14, 0x85, 0x00, 0x0c, 0x07, 0x84, 0xff, 0x94, + 0x2a, 0x09, 0x02, 0x0d, 0x36, 0xad, 0xff, 0x6b, 0x02, 0x81, 0x00, 0x0c, + 0x10, 0xbf, 0xff, 0xbb, 0x34, 0x09, 0x05, 0x1a, 0x61, 0xea, 0x91, 0xff, + 0x88, 0xa2, 0x00, 0x05, 0x36, 0xff, 0xea, 0x71, 0x26, 0x01, 0xa2, 0x00, + 0x05, 0x05, 0x35, 0x8c, 0xff, 0xff, 0x17, 0x85, 0x00, 0x05, 0x04, 0x66, + 0xff, 0xdd, 0x46, 0x01, 0x81, 0x00, 0x05, 0x27, 0xff, 0x36, 0x0b, 0xff, + 0x7a, 0x81, 0x00, 0x06, 0x63, 0xff, 0x11, 0x00, 0x3f, 0xff, 0x14, 0x80, + 0x00, 0x02, 0x6f, 0xff, 0x7e, 0x81, 0x00, 0x03, 0x02, 0xaf, 0xff, 0x4f, + 0x82, 0x00, 0x02, 0x80, 0xff, 0x8f, 0x80, 0x04, 0x06, 0x06, 0x12, 0x26, + 0x68, 0xff, 0xff, 0x43, 0x80, 0x00, 0x03, 0x38, 0xff, 0xff, 0x29, 0x8b, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x25, 0xff, 0xff, 0x2a, + 0x80, 0x00, 0x00, 0x80, 0x87, 0xff, 0x00, 0xc2, 0x82, 0x00, 0x00, 0x2d, + 0x88, 0xff, 0x00, 0x45, 0x80, 0x00, 0x03, 0x38, 0xff, 0xff, 0x29, 0x80, + 0x00, 0x00, 0x45, 0x83, 0xff, 0x00, 0x06, 0x80, 0x00, 0x02, 0x80, 0xff, + 0x96, 0x83, 0x15, 0x03, 0x18, 0xff, 0xff, 0x53, 0x86, 0x00, 0x02, 0xb1, + 0xff, 0x69, 0x8e, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x43, 0x82, 0x00, 0x00, + 0x80, 0x80, 0xff, 0x04, 0xa5, 0x99, 0xff, 0xe3, 0x22, 0x86, 0x00, 0x02, + 0x7c, 0xff, 0x98, 0x89, 0x00, 0x0e, 0x1d, 0xff, 0xc2, 0x00, 0x00, 0x4d, + 0xff, 0xa5, 0xff, 0x2f, 0x00, 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, 0x0c, + 0x80, 0xff, 0x4d, 0x00, 0x00, 0x52, 0xff, 0x7b, 0x00, 0x00, 0x80, 0xff, + 0x53, 0x80, 0x00, 0x03, 0x54, 0xff, 0xff, 0x14, 0x84, 0x00, 0x03, 0x32, + 0xff, 0xff, 0x2e, 0x80, 0x00, 0x00, 0x80, 0x86, 0xff, 0x01, 0xca, 0x32, + 0x81, 0x00, 0x03, 0x56, 0xff, 0xff, 0x12, 0x84, 0x00, 0x03, 0x31, 0xff, + 0xff, 0x31, 0x80, 0x00, 0x00, 0x80, 0x84, 0xff, 0x02, 0xab, 0x50, 0x17, + 0x87, 0x00, 0x03, 0x15, 0x38, 0x65, 0xad, 0x80, 0xff, 0x01, 0x63, 0x05, + 0x86, 0x00, 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, 0x03, 0x07, 0xff, 0xff, + 0x4d, 0x84, 0x00, 0x02, 0x7c, 0xff, 0x8d, 0x82, 0x00, 0x03, 0x1b, 0xff, + 0xff, 0x2c, 0x80, 0x00, 0x03, 0x49, 0xff, 0xc2, 0x06, 0x81, 0x00, 0x0e, + 0x41, 0xff, 0x96, 0x00, 0x00, 0x9d, 0xd8, 0x1e, 0xff, 0x6f, 0x00, 0x02, + 0xe3, 0xff, 0x23, 0x84, 0x00, 0x00, 0x5c, 0x80, 0xff, 0x00, 0x38, 0x89, + 0x00, 0x04, 0x2d, 0xff, 0xff, 0xd1, 0x14, 0x88, 0x00, 0x04, 0x01, 0x73, + 0xff, 0xb3, 0x10, 0x89, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x8c, 0x00, + 0x03, 0x08, 0xb5, 0xff, 0x3e, 0x8b, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, + 0x84, 0x00, 0x03, 0x13, 0xff, 0xa0, 0x01, 0x82, 0x00, 0x03, 0x14, 0xff, + 0xa5, 0x02, 0xa4, 0x00, 0x04, 0x05, 0x3a, 0x74, 0x9a, 0xc4, 0x82, 0xff, + 0x00, 0x66, 0x82, 0x00, 0x03, 0x40, 0xff, 0xff, 0x05, 0x83, 0x00, 0x02, + 0x68, 0xff, 0x96, 0x80, 0x00, 0x03, 0x12, 0xff, 0xff, 0x34, 0x8a, 0x00, + 0x03, 0x07, 0xff, 0xff, 0x41, 0x83, 0x00, 0x03, 0x1e, 0xff, 0xff, 0x22, + 0x80, 0x00, 0x00, 0x0f, 0x89, 0xff, 0x00, 0xa5, 0x84, 0x00, 0x02, 0x4b, + 0xff, 0xb9, 0x88, 0x00, 0x02, 0xea, 0xff, 0x4b, 0x83, 0x00, 0x03, 0x17, + 0xff, 0xff, 0x2a, 0x81, 0x00, 0x02, 0x40, 0xff, 0xe3, 0x83, 0x00, 0x03, + 0x0f, 0xff, 0xff, 0x2d, 0x86, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, 0x8b, + 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x06, 0x7c, 0xff, 0x69, + 0x5a, 0xff, 0xff, 0x22, 0x8b, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x84, + 0x00, 0x02, 0x50, 0xff, 0x7c, 0x80, 0x00, 0x02, 0x74, 0xff, 0x50, 0x80, + 0x00, 0x02, 0xb1, 0xff, 0x31, 0x80, 0x00, 0x02, 0x40, 0xff, 0xe3, 0x83, + 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x80, 0x00, 0x03, 0x14, 0xff, 0xff, + 0x36, 0x84, 0x00, 0x02, 0x5d, 0xff, 0xb9, 0x81, 0x00, 0x03, 0x40, 0xff, + 0xff, 0x07, 0x83, 0x00, 0x02, 0x66, 0xff, 0x98, 0x80, 0x00, 0x03, 0x07, + 0xff, 0xff, 0x40, 0x83, 0x00, 0x03, 0x1e, 0xff, 0xff, 0x24, 0x83, 0x00, + 0x02, 0xdd, 0xff, 0x63, 0x8a, 0x00, 0x01, 0x1e, 0xbb, 0x80, 0xff, 0x03, + 0x92, 0x54, 0x28, 0x04, 0x86, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x2f, 0x88, + 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, + 0x82, 0x00, 0x03, 0x45, 0xff, 0xff, 0x12, 0x80, 0x00, 0x03, 0x37, 0xff, + 0xff, 0x1b, 0x81, 0x00, 0x0e, 0x5d, 0xff, 0x6d, 0x00, 0x00, 0x67, 0xff, + 0x4d, 0xff, 0x3c, 0x00, 0x00, 0xbd, 0xff, 0x34, 0x84, 0x00, 0x00, 0x5f, + 0x80, 0xff, 0x00, 0x29, 0x86, 0x00, 0x03, 0x28, 0xff, 0xff, 0x1a, 0x80, + 0x00, 0x03, 0x25, 0xff, 0xff, 0x17, 0x87, 0x00, 0x03, 0x43, 0xff, 0xd8, + 0x21, 0x87, 0x00, 0x04, 0x0d, 0x50, 0xff, 0xff, 0x3b, 0x8c, 0x00, 0x02, + 0x74, 0xff, 0x4b, 0x8c, 0x00, 0x04, 0x5e, 0xff, 0xc7, 0x39, 0x06, 0x82, + 0x00, 0x00, 0x13, 0x83, 0x00, 0x06, 0x0b, 0x43, 0x8a, 0xcd, 0xbf, 0x71, + 0x1d, 0x86, 0x00, 0x05, 0x04, 0x66, 0xff, 0xdd, 0x46, 0x01, 0x99, 0x00, + 0x02, 0x66, 0xff, 0x42, 0x95, 0x00, 0x05, 0x04, 0x11, 0x11, 0x1c, 0xff, + 0x45, 0x81, 0x11, 0x01, 0x68, 0xa6, 0x80, 0x11, 0x00, 0x06, 0x85, 0x00, + 0x08, 0x31, 0xff, 0x31, 0x0a, 0x3f, 0xb3, 0xff, 0xab, 0x06, 0x84, 0x00, + 0x13, 0x61, 0xff, 0x2c, 0x33, 0xff, 0x9f, 0x37, 0x3d, 0xbf, 0xd8, 0x16, + 0x00, 0x66, 0xff, 0x78, 0x02, 0x01, 0x80, 0xff, 0x51, 0x80, 0x00, 0x02, + 0xa2, 0xff, 0x19, 0x94, 0x00, 0x03, 0x28, 0xff, 0xff, 0x1f, 0x8f, 0x00, + 0x03, 0x3c, 0xff, 0xff, 0x09, 0x99, 0x00, 0x02, 0x59, 0xff, 0x34, 0x99, + 0x00, 0x00, 0x3b, 0x84, 0xff, 0x00, 0x1b, 0x97, 0x00, 0x03, 0x1d, 0xff, + 0xff, 0x1e, 0x86, 0x00, 0x03, 0x1b, 0xff, 0xff, 0x1e, 0x84, 0x00, 0x02, + 0x43, 0xff, 0xdd, 0x87, 0x00, 0x02, 0x92, 0xff, 0x5c, 0x8a, 0x00, 0x04, + 0x3a, 0xdd, 0xff, 0x79, 0x08, 0x8d, 0x00, 0x03, 0x2d, 0xea, 0xff, 0x40, + 0x81, 0x00, 0x02, 0x43, 0xff, 0x58, 0x82, 0x00, 0x02, 0x63, 0xff, 0x89, + 0x8d, 0x00, 0x02, 0x7e, 0xff, 0xa0, 0x81, 0x00, 0x02, 0x9f, 0xff, 0xa2, + 0x84, 0x00, 0x02, 0x70, 0xff, 0x94, 0x86, 0x00, 0x02, 0x79, 0xff, 0x79, + 0x86, 0x00, 0x03, 0x58, 0xff, 0xa5, 0x09, 0x82, 0x00, 0x03, 0x15, 0xd8, + 0xff, 0x40, 0x82, 0x00, 0x01, 0x24, 0xc2, 0x82, 0xff, 0x04, 0xe3, 0x3f, + 0x61, 0xff, 0x78, 0xa2, 0x00, 0x07, 0x0f, 0x57, 0xc2, 0xff, 0xff, 0x9a, + 0x3d, 0x08, 0x87, 0x00, 0x8a, 0x02, 0x87, 0x00, 0x07, 0x10, 0x4d, 0xb7, + 0xff, 0xff, 0xa8, 0x47, 0x06, 0x85, 0x00, 0x03, 0x6f, 0xff, 0xb1, 0x1e, + 0x83, 0x00, 0x05, 0x2e, 0xff, 0x2f, 0x15, 0xff, 0x67, 0x81, 0x00, 0x0c, + 0x9d, 0xbb, 0x00, 0x00, 0x50, 0xff, 0x06, 0x00, 0x00, 0x0d, 0xe3, 0xff, + 0x3b, 0x82, 0x04, 0x03, 0x58, 0xff, 0xad, 0x02, 0x81, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x84, 0x00, 0x09, 0x47, 0xff, 0xff, 0x1d, 0x00, 0x00, 0x30, + 0xff, 0xff, 0x31, 0x8b, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, + 0x2f, 0xff, 0xff, 0x21, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8b, 0x00, + 0x00, 0x2d, 0x88, 0xff, 0x00, 0x45, 0x80, 0x00, 0x03, 0x2f, 0xff, 0xff, + 0x31, 0x80, 0x00, 0x00, 0x0a, 0x80, 0x15, 0x03, 0x52, 0xff, 0xff, 0x06, + 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, + 0x53, 0x86, 0x00, 0x02, 0xb1, 0xff, 0x69, 0x8e, 0x00, 0x03, 0x0d, 0xff, + 0xff, 0x43, 0x82, 0x00, 0x09, 0x80, 0xff, 0xff, 0xa6, 0x12, 0x17, 0xc7, + 0xff, 0xaf, 0x0d, 0x85, 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x0e, + 0x1d, 0xff, 0xc2, 0x00, 0x00, 0x13, 0xff, 0xff, 0xbb, 0x04, 0x00, 0x17, + 0xff, 0xff, 0x04, 0x80, 0x00, 0x0c, 0x80, 0xff, 0x4d, 0x00, 0x00, 0x0e, + 0xd4, 0xff, 0x1e, 0x00, 0x80, 0xff, 0x53, 0x80, 0x00, 0x03, 0x49, 0xff, + 0xff, 0x1a, 0x84, 0x00, 0x03, 0x3a, 0xff, 0xff, 0x26, 0x80, 0x00, 0x00, + 0x80, 0x83, 0xff, 0x03, 0xb9, 0x88, 0x4b, 0x0e, 0x82, 0x00, 0x03, 0x50, + 0xff, 0xff, 0x16, 0x84, 0x00, 0x03, 0x36, 0xff, 0xff, 0x2b, 0x80, 0x00, + 0x02, 0x80, 0xff, 0x90, 0x80, 0x07, 0x03, 0x61, 0xff, 0xc7, 0x12, 0x8b, + 0x00, 0x05, 0x01, 0x22, 0x6f, 0xff, 0xff, 0x65, 0x86, 0x00, 0x02, 0xaa, + 0xff, 0x69, 0x85, 0x00, 0x03, 0x07, 0xff, 0xff, 0x4d, 0x84, 0x00, 0x02, + 0x7c, 0xff, 0x8d, 0x83, 0x00, 0x02, 0x8d, 0xff, 0x6e, 0x80, 0x00, 0x02, + 0x9f, 0xff, 0x5c, 0x82, 0x00, 0x0e, 0x28, 0xff, 0xd4, 0x01, 0x13, 0xff, + 0x7f, 0x01, 0xbf, 0xc7, 0x04, 0x11, 0xff, 0xff, 0x0e, 0x83, 0x00, 0x06, + 0x29, 0xff, 0xff, 0x72, 0xff, 0xc7, 0x13, 0x89, 0x00, 0x02, 0xa8, 0xff, + 0x6c, 0x89, 0x00, 0x03, 0x4d, 0xff, 0xe3, 0x23, 0x8a, 0x00, 0x03, 0x34, + 0xff, 0xff, 0x07, 0x8d, 0x00, 0x03, 0x3b, 0xff, 0xb9, 0x09, 0x8a, 0x00, + 0x03, 0x26, 0xff, 0xff, 0x15, 0x84, 0x00, 0x02, 0x52, 0xff, 0x44, 0x84, + 0x00, 0x02, 0x79, 0xff, 0x2a, 0xa3, 0x00, 0x0b, 0x0e, 0x94, 0xff, 0xff, + 0xc2, 0x80, 0x6f, 0x6d, 0x6d, 0xbb, 0xff, 0x66, 0x82, 0x00, 0x02, 0x40, + 0xff, 0xea, 0x84, 0x00, 0x02, 0x61, 0xff, 0xa3, 0x80, 0x00, 0x03, 0x19, + 0xff, 0xff, 0x30, 0x8a, 0x00, 0x03, 0x0c, 0xff, 0xff, 0x3c, 0x83, 0x00, + 0x03, 0x1b, 0xff, 0xff, 0x22, 0x80, 0x00, 0x03, 0x15, 0xff, 0xff, 0xb7, + 0x86, 0xa3, 0x00, 0x91, 0x84, 0x00, 0x02, 0x4b, 0xff, 0xb9, 0x87, 0x00, + 0x03, 0x04, 0xff, 0xff, 0x47, 0x83, 0x00, 0x03, 0x11, 0xff, 0xff, 0x2a, + 0x81, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, + 0x2d, 0x86, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, 0x8b, 0x00, 0x03, 0x04, + 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, 0xca, 0x80, 0xff, 0x01, + 0x87, 0x03, 0x8a, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x84, 0x00, 0x02, + 0x50, 0xff, 0x78, 0x80, 0x00, 0x02, 0x74, 0xff, 0x50, 0x80, 0x00, 0x02, + 0xb1, 0xff, 0x31, 0x80, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, + 0x0f, 0xff, 0xff, 0x2d, 0x80, 0x00, 0x03, 0x19, 0xff, 0xff, 0x31, 0x84, + 0x00, 0x02, 0x55, 0xff, 0xd8, 0x81, 0x00, 0x03, 0x40, 0xff, 0xff, 0x01, + 0x83, 0x00, 0x02, 0x61, 0xff, 0xa3, 0x80, 0x00, 0x03, 0x0c, 0xff, 0xff, + 0x3c, 0x83, 0x00, 0x03, 0x1b, 0xff, 0xff, 0x24, 0x83, 0x00, 0x02, 0xdd, + 0xff, 0x49, 0x8b, 0x00, 0x02, 0x0a, 0x47, 0x9a, 0x81, 0xff, 0x02, 0xb1, + 0x48, 0x04, 0x84, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x2f, 0x88, 0x00, 0x02, + 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x82, 0x00, + 0x03, 0x0e, 0xe3, 0xff, 0x49, 0x80, 0x00, 0x02, 0x83, 0xff, 0x88, 0x82, + 0x00, 0x0e, 0x3f, 0xff, 0x96, 0x00, 0x04, 0xc2, 0xa2, 0x0e, 0xff, 0x76, + 0x00, 0x0e, 0xff, 0xff, 0x1b, 0x84, 0x00, 0x04, 0x21, 0xff, 0xff, 0xad, + 0x06, 0x86, 0x00, 0x03, 0x01, 0x9a, 0xff, 0x5b, 0x80, 0x00, 0x02, 0x68, + 0xff, 0x7e, 0x87, 0x00, 0x03, 0x29, 0xea, 0xff, 0x37, 0x87, 0x00, 0x04, + 0x91, 0xff, 0xff, 0x98, 0x30, 0x8d, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8c, + 0x00, 0x05, 0x01, 0x46, 0xb1, 0xff, 0xff, 0x5f, 0x98, 0x00, 0x03, 0x6f, + 0xff, 0xb1, 0x1e, 0x9b, 0x00, 0x02, 0x61, 0xff, 0x3e, 0x95, 0x00, 0x00, + 0x22, 0x8b, 0xff, 0x00, 0x2f, 0x85, 0x00, 0x08, 0x31, 0xff, 0x31, 0x00, + 0x00, 0x17, 0xc7, 0xff, 0x3d, 0x83, 0x00, 0x19, 0x2e, 0xff, 0x5d, 0x00, + 0x85, 0xff, 0x1f, 0x00, 0x00, 0x3f, 0xff, 0x51, 0x13, 0xff, 0xff, 0x19, + 0x00, 0x00, 0x13, 0xca, 0xea, 0x26, 0x00, 0x1e, 0xff, 0x9a, 0x95, 0x00, + 0x03, 0x28, 0xff, 0xff, 0x1f, 0x8f, 0x00, 0x03, 0x3c, 0xff, 0xff, 0x08, + 0x99, 0x00, 0x02, 0x59, 0xff, 0x34, 0x99, 0x00, 0x00, 0x3b, 0x84, 0xff, + 0x00, 0x1b, 0x97, 0x00, 0x02, 0x81, 0xff, 0x67, 0x87, 0x00, 0x03, 0x10, + 0xff, 0xff, 0x2e, 0x84, 0x00, 0x02, 0x58, 0xff, 0xa6, 0x87, 0x00, 0x02, + 0x92, 0xff, 0x5c, 0x88, 0x00, 0x05, 0x03, 0x5b, 0xff, 0xff, 0x50, 0x02, + 0x8f, 0x00, 0x02, 0x6f, 0xff, 0x9f, 0x80, 0x00, 0x03, 0x1c, 0xdd, 0x90, + 0x05, 0x82, 0x00, 0x02, 0x63, 0xff, 0x89, 0x8d, 0x00, 0x03, 0x50, 0xff, + 0xe3, 0x01, 0x80, 0x00, 0x02, 0x82, 0xff, 0x81, 0x84, 0x00, 0x02, 0x4d, + 0xff, 0xc2, 0x85, 0x00, 0x03, 0x12, 0xff, 0xff, 0x30, 0x85, 0x00, 0x03, + 0x06, 0xd8, 0xff, 0x4a, 0x84, 0x00, 0x02, 0x77, 0xff, 0x89, 0x83, 0x00, + 0x0a, 0x0e, 0x50, 0x8b, 0xab, 0x8f, 0x59, 0x19, 0x00, 0x82, 0xff, 0x58, + 0xa4, 0x00, 0x07, 0x07, 0x3b, 0x94, 0xff, 0xff, 0xc4, 0x57, 0x16, 0x84, + 0x00, 0x00, 0x36, 0x8a, 0xff, 0x00, 0x17, 0x84, 0x00, 0x07, 0x23, 0x6c, + 0xe3, 0xff, 0xff, 0x7b, 0x2d, 0x02, 0x86, 0x00, 0x03, 0x2a, 0xff, 0xea, + 0x1f, 0x84, 0x00, 0x05, 0x31, 0xff, 0x2d, 0x17, 0xff, 0x62, 0x80, 0x00, + 0x06, 0x0d, 0xff, 0x7c, 0x00, 0x00, 0x6f, 0xa2, 0x80, 0x00, 0x00, 0x43, + 0x88, 0xff, 0x00, 0x29, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, + 0x09, 0x05, 0xd4, 0xff, 0x57, 0x00, 0x00, 0x1d, 0xff, 0xff, 0x45, 0x8b, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x4a, 0xff, 0xff, 0x0d, + 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8b, 0x00, 0x03, 0x2d, 0xff, 0xff, + 0x22, 0x89, 0x00, 0x03, 0x1b, 0xff, 0xff, 0x48, 0x84, 0x00, 0x03, 0x43, + 0xff, 0xff, 0x06, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, + 0x04, 0xff, 0xff, 0x53, 0x86, 0x00, 0x02, 0xb1, 0xff, 0x69, 0x8e, 0x00, + 0x03, 0x0d, 0xff, 0xff, 0x43, 0x82, 0x00, 0x0a, 0x80, 0xff, 0xb9, 0x13, + 0x00, 0x00, 0x30, 0xff, 0xff, 0x7e, 0x02, 0x84, 0x00, 0x02, 0x7c, 0xff, + 0x98, 0x89, 0x00, 0x02, 0x1d, 0xff, 0xc2, 0x80, 0x00, 0x08, 0x7b, 0xff, + 0x57, 0x00, 0x00, 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, 0x02, 0x80, 0xff, + 0x4d, 0x80, 0x00, 0x06, 0x5d, 0xff, 0x6f, 0x00, 0x7f, 0xff, 0x53, 0x80, + 0x00, 0x03, 0x36, 0xff, 0xff, 0x2c, 0x84, 0x00, 0x03, 0x50, 0xff, 0xff, + 0x15, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8a, 0x00, 0x03, 0x44, 0xff, + 0xff, 0x20, 0x84, 0x00, 0x03, 0x41, 0xff, 0xff, 0x22, 0x80, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x80, 0x00, 0x04, 0x0a, 0xb5, 0xff, 0x7b, 0x01, 0x8d, + 0x00, 0x03, 0x5d, 0xff, 0xff, 0x16, 0x85, 0x00, 0x02, 0xaa, 0xff, 0x69, + 0x85, 0x00, 0x03, 0x06, 0xff, 0xff, 0x50, 0x84, 0x00, 0x02, 0x82, 0xff, + 0x89, 0x83, 0x00, 0x08, 0x3d, 0xff, 0xd8, 0x0a, 0x00, 0x1f, 0xff, 0xff, + 0x1e, 0x82, 0x00, 0x0d, 0x13, 0xff, 0xff, 0x0e, 0x3a, 0xff, 0x4b, 0x00, + 0x6f, 0xff, 0x20, 0x20, 0xff, 0xc2, 0x83, 0x00, 0x08, 0x0b, 0xaf, 0xff, + 0x5d, 0x03, 0x8b, 0xff, 0x82, 0x02, 0x88, 0x00, 0x02, 0xa3, 0xff, 0x69, + 0x88, 0x00, 0x03, 0x2e, 0xff, 0xff, 0x3f, 0x8b, 0x00, 0x03, 0x34, 0xff, + 0xff, 0x07, 0x8d, 0x00, 0x03, 0x02, 0x96, 0xff, 0x54, 0x8a, 0x00, 0x03, + 0x26, 0xff, 0xff, 0x15, 0x83, 0x00, 0x03, 0x05, 0xb9, 0xdd, 0x0d, 0x84, + 0x00, 0x02, 0x2d, 0xff, 0x76, 0xa3, 0x00, 0x04, 0x75, 0xff, 0xdd, 0x35, + 0x04, 0x81, 0x00, 0x02, 0x89, 0xff, 0x66, 0x82, 0x00, 0x03, 0x40, 0xff, + 0xff, 0x02, 0x83, 0x00, 0x02, 0x68, 0xff, 0x95, 0x80, 0x00, 0x03, 0x14, + 0xff, 0xff, 0x35, 0x8a, 0x00, 0x03, 0x08, 0xff, 0xff, 0x40, 0x83, 0x00, + 0x03, 0x20, 0xff, 0xff, 0x22, 0x80, 0x00, 0x03, 0x0e, 0xff, 0xff, 0x3b, + 0x8e, 0x00, 0x02, 0x4b, 0xff, 0xb9, 0x87, 0x00, 0x03, 0x01, 0xff, 0xff, + 0x4a, 0x83, 0x00, 0x03, 0x16, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x02, 0x40, + 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x86, 0x00, 0x03, + 0x24, 0xff, 0xff, 0x17, 0x8b, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, + 0x00, 0x07, 0x7c, 0xff, 0xff, 0x84, 0x2d, 0xd8, 0xff, 0x52, 0x8a, 0x00, + 0x03, 0x34, 0xff, 0xff, 0x07, 0x84, 0x00, 0x02, 0x50, 0xff, 0x78, 0x80, + 0x00, 0x02, 0x74, 0xff, 0x50, 0x80, 0x00, 0x02, 0xb1, 0xff, 0x31, 0x80, + 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, + 0x80, 0x00, 0x03, 0x13, 0xff, 0xff, 0x36, 0x84, 0x00, 0x02, 0x5d, 0xff, + 0xb5, 0x81, 0x00, 0x03, 0x40, 0xff, 0xff, 0x04, 0x83, 0x00, 0x02, 0x67, + 0xff, 0x96, 0x80, 0x00, 0x03, 0x08, 0xff, 0xff, 0x41, 0x83, 0x00, 0x03, + 0x22, 0xff, 0xff, 0x24, 0x83, 0x00, 0x02, 0xdd, 0xff, 0x43, 0x8e, 0x00, + 0x07, 0x13, 0x37, 0x64, 0xc2, 0xff, 0xff, 0x77, 0x01, 0x83, 0x00, 0x03, + 0x0d, 0xff, 0xff, 0x2f, 0x88, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, + 0x03, 0x10, 0xff, 0xff, 0x2d, 0x83, 0x00, 0x08, 0x6e, 0xff, 0xa2, 0x01, + 0x00, 0x16, 0xff, 0xff, 0x36, 0x82, 0x00, 0x0e, 0x25, 0xff, 0xdd, 0x02, + 0x26, 0xff, 0x56, 0x00, 0x8a, 0xd8, 0x07, 0x23, 0xff, 0xea, 0x06, 0x83, + 0x00, 0x05, 0x07, 0x9c, 0xff, 0xd8, 0xff, 0x63, 0x87, 0x00, 0x08, 0x3d, + 0xff, 0xc7, 0x08, 0x00, 0x0b, 0xd8, 0xff, 0x2f, 0x86, 0x00, 0x03, 0x17, + 0xc2, 0xff, 0x55, 0x88, 0x00, 0x04, 0xa3, 0xff, 0xff, 0x83, 0x26, 0x8d, + 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8d, 0x00, 0x04, 0x39, 0x9c, 0xff, 0xff, + 0x69, 0x97, 0x00, 0x03, 0x2a, 0xff, 0xea, 0x1f, 0x9c, 0x00, 0x02, 0x56, + 0xc2, 0x37, 0x95, 0x00, 0x04, 0x0a, 0x2a, 0x2a, 0x70, 0xbb, 0x81, 0x2a, + 0x02, 0x36, 0xff, 0x58, 0x80, 0x2a, 0x05, 0x0e, 0x00, 0x00, 0x02, 0x19, + 0x0c, 0x80, 0x00, 0x02, 0x31, 0xff, 0x31, 0x80, 0x00, 0x02, 0x6c, 0xff, + 0x65, 0x82, 0x00, 0x0f, 0x0f, 0xb9, 0x99, 0x06, 0x00, 0xd1, 0xff, 0x04, + 0x00, 0x00, 0x1e, 0xff, 0x78, 0x2f, 0xff, 0xc4, 0x81, 0x00, 0x06, 0x34, + 0xff, 0xb9, 0x16, 0x61, 0xff, 0x43, 0x95, 0x00, 0x03, 0x22, 0xff, 0xff, + 0x25, 0x8f, 0x00, 0x03, 0x43, 0xff, 0xff, 0x04, 0x99, 0x00, 0x02, 0x59, + 0xff, 0x34, 0xbb, 0x00, 0x03, 0x2e, 0xff, 0xd4, 0x11, 0x88, 0x00, 0x02, + 0xbb, 0xff, 0x49, 0x84, 0x00, 0x02, 0x80, 0xff, 0x6c, 0x87, 0x00, 0x02, + 0x92, 0xff, 0x5c, 0x87, 0x00, 0x04, 0x06, 0x77, 0xff, 0xc4, 0x2b, 0x86, + 0x00, 0x03, 0x09, 0x37, 0x46, 0x1a, 0x84, 0x00, 0x06, 0x4f, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x55, 0x8a, 0xff, 0x00, 0x31, 0x8a, 0x00, 0x02, 0x56, + 0xff, 0xc7, 0x81, 0x00, 0x02, 0x59, 0xff, 0xa2, 0x84, 0x00, 0x02, 0x50, + 0xff, 0xb3, 0x85, 0x00, 0x03, 0x42, 0xff, 0xd8, 0x07, 0x85, 0x00, 0x03, + 0x14, 0xff, 0xff, 0x35, 0x84, 0x00, 0x02, 0x5e, 0xff, 0xb5, 0x8a, 0x00, + 0x03, 0x06, 0xcd, 0xff, 0x35, 0xa7, 0x00, 0x07, 0x23, 0x6a, 0xe3, 0xff, + 0xff, 0x78, 0x2a, 0x01, 0x81, 0x00, 0x00, 0x36, 0x8a, 0xff, 0x00, 0x17, + 0x81, 0x00, 0x07, 0x06, 0x38, 0x92, 0xff, 0xff, 0xc2, 0x57, 0x16, 0x89, + 0x00, 0x02, 0x5c, 0xff, 0x77, 0x85, 0x00, 0x05, 0x29, 0xff, 0x34, 0x0d, + 0xff, 0x6e, 0x80, 0x00, 0x06, 0x3a, 0xff, 0x5a, 0x00, 0x01, 0xb9, 0x61, + 0x80, 0x00, 0x00, 0x99, 0x88, 0xff, 0x00, 0x6c, 0x81, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x85, 0x00, 0x08, 0xad, 0xff, 0x71, 0x00, 0x00, 0x06, 0xd8, + 0xff, 0x74, 0x85, 0x00, 0x02, 0x3f, 0x26, 0x01, 0x80, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x84, 0x00, 0x02, 0x8b, 0xff, 0xa0, 0x81, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x8b, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x22, 0x89, 0x00, 0x03, + 0x05, 0xd1, 0xff, 0x78, 0x84, 0x00, 0x03, 0x43, 0xff, 0xff, 0x06, 0x80, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, + 0x86, 0x00, 0x02, 0xb1, 0xff, 0x69, 0x87, 0x00, 0x01, 0x09, 0x1d, 0x82, + 0x00, 0x03, 0x11, 0xff, 0xff, 0x3f, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x81, 0x00, 0x03, 0x54, 0xff, 0xff, 0x50, 0x84, 0x00, 0x02, 0x7c, 0xff, + 0x98, 0x89, 0x00, 0x02, 0x1d, 0xff, 0xc2, 0x80, 0x00, 0x08, 0x08, 0x0f, + 0x06, 0x00, 0x00, 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, 0x02, 0x80, 0xff, + 0x4d, 0x80, 0x00, 0x06, 0x14, 0xea, 0xff, 0x17, 0x7a, 0xff, 0x53, 0x80, + 0x00, 0x03, 0x1b, 0xff, 0xff, 0x50, 0x84, 0x00, 0x03, 0x7d, 0xff, 0xc4, + 0x01, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8a, 0x00, 0x03, 0x2d, 0xff, + 0xff, 0x35, 0x84, 0x00, 0x03, 0x5a, 0xff, 0xff, 0x0f, 0x80, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x81, 0x00, 0x03, 0x33, 0xff, 0xff, 0x3b, 0x83, 0x00, + 0x01, 0x01, 0x0a, 0x85, 0x00, 0x03, 0x1b, 0xff, 0xff, 0x32, 0x85, 0x00, + 0x02, 0xaa, 0xff, 0x69, 0x85, 0x00, 0x03, 0x01, 0xea, 0xff, 0x5a, 0x84, + 0x00, 0x02, 0x98, 0xff, 0x79, 0x83, 0x00, 0x07, 0x0a, 0xd4, 0xff, 0x37, + 0x00, 0x57, 0xff, 0x96, 0x83, 0x00, 0x0d, 0x02, 0xd4, 0xff, 0x1b, 0x69, + 0xff, 0x22, 0x00, 0x3b, 0xff, 0x47, 0x30, 0xff, 0x84, 0x83, 0x00, 0x08, + 0x6b, 0xff, 0xa5, 0x07, 0x00, 0x18, 0xd8, 0xff, 0x45, 0x88, 0x00, 0x02, + 0xa3, 0xff, 0x69, 0x87, 0x00, 0x03, 0x18, 0xc7, 0xff, 0x63, 0x8c, 0x00, + 0x03, 0x34, 0xff, 0xff, 0x07, 0x8e, 0x00, 0x03, 0x29, 0xff, 0xd8, 0x14, + 0x89, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0xb6, 0x00, 0x03, 0x0c, 0xff, + 0xff, 0x55, 0x83, 0x00, 0x02, 0xa0, 0xff, 0x66, 0x82, 0x00, 0x03, 0x40, + 0xff, 0xff, 0x0c, 0x83, 0x00, 0x02, 0x80, 0xff, 0x7c, 0x80, 0x00, 0x03, + 0x06, 0xea, 0xff, 0x49, 0x8a, 0x00, 0x03, 0x01, 0xd4, 0xff, 0x50, 0x83, + 0x00, 0x03, 0x32, 0xff, 0xff, 0x22, 0x80, 0x00, 0x03, 0x03, 0xd1, 0xff, + 0x50, 0x8e, 0x00, 0x02, 0x4b, 0xff, 0xb9, 0x88, 0x00, 0x02, 0xbb, 0xff, + 0x58, 0x83, 0x00, 0x03, 0x28, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x02, 0x40, + 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x86, 0x00, 0x03, + 0x24, 0xff, 0xff, 0x17, 0x8b, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, + 0x00, 0x08, 0x7c, 0xff, 0x81, 0x03, 0x00, 0x41, 0xff, 0xff, 0x28, 0x89, + 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x84, 0x00, 0x02, 0x50, 0xff, 0x78, + 0x80, 0x00, 0x02, 0x74, 0xff, 0x50, 0x80, 0x00, 0x02, 0xb1, 0xff, 0x31, + 0x80, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, + 0x2d, 0x80, 0x00, 0x03, 0x06, 0xea, 0xff, 0x49, 0x84, 0x00, 0x02, 0x76, + 0xff, 0x8b, 0x81, 0x00, 0x03, 0x40, 0xff, 0xff, 0x0e, 0x83, 0x00, 0x02, + 0x7c, 0xff, 0x7b, 0x80, 0x00, 0x03, 0x01, 0xd4, 0xff, 0x52, 0x83, 0x00, + 0x03, 0x35, 0xff, 0xff, 0x24, 0x83, 0x00, 0x02, 0xdd, 0xff, 0x43, 0x91, + 0x00, 0x04, 0x05, 0x4e, 0xff, 0xff, 0x27, 0x83, 0x00, 0x03, 0x0d, 0xff, + 0xff, 0x2f, 0x88, 0x00, 0x02, 0x3f, 0xff, 0xe3, 0x83, 0x00, 0x03, 0x19, + 0xff, 0xff, 0x2d, 0x83, 0x00, 0x08, 0x28, 0xff, 0xff, 0x22, 0x00, 0x50, + 0xff, 0xbf, 0x06, 0x82, 0x00, 0x0d, 0x0f, 0xff, 0xff, 0x0f, 0x5a, 0xff, + 0x24, 0x00, 0x49, 0xff, 0x2d, 0x36, 0xff, 0x9c, 0x84, 0x00, 0x06, 0x65, + 0xff, 0x92, 0x1e, 0xd4, 0xff, 0x35, 0x86, 0x00, 0x08, 0x07, 0xc2, 0xff, + 0x3a, 0x00, 0x41, 0xff, 0xad, 0x03, 0x85, 0x00, 0x04, 0x0b, 0x9f, 0xff, + 0x75, 0x02, 0x88, 0x00, 0x05, 0x06, 0x1d, 0x68, 0xff, 0xff, 0x34, 0x8c, + 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8c, 0x00, 0x05, 0x58, 0xff, 0xdd, 0x4f, + 0x16, 0x04, 0x97, 0x00, 0x02, 0x5c, 0xff, 0x77, 0xbb, 0x00, 0x01, 0x79, + 0x77, 0x81, 0x00, 0x02, 0x25, 0xff, 0x1d, 0x82, 0x00, 0x03, 0x02, 0xb3, + 0xff, 0x49, 0x80, 0x00, 0x02, 0x31, 0xff, 0x31, 0x80, 0x00, 0x02, 0x67, + 0xff, 0x68, 0x81, 0x00, 0x07, 0x01, 0x7a, 0xdd, 0x1c, 0x00, 0x02, 0xff, + 0xe3, 0x80, 0x00, 0x05, 0x18, 0xff, 0x83, 0x31, 0xff, 0xc4, 0x82, 0x00, + 0x05, 0x50, 0xff, 0xa6, 0xd1, 0xc4, 0x0a, 0x95, 0x00, 0x03, 0x16, 0xff, + 0xff, 0x32, 0x8f, 0x00, 0x02, 0x54, 0xff, 0xbd, 0x9a, 0x00, 0x02, 0x59, + 0xff, 0x34, 0xac, 0x00, 0x00, 0x02, 0x80, 0x09, 0x87, 0x00, 0x03, 0x04, + 0x9f, 0xff, 0x50, 0x89, 0x00, 0x02, 0x6c, 0xff, 0x8c, 0x83, 0x00, 0x03, + 0x0c, 0xe3, 0xff, 0x3b, 0x87, 0x00, 0x02, 0x92, 0xff, 0x5c, 0x86, 0x00, + 0x04, 0x06, 0x7d, 0xff, 0xaa, 0x1a, 0x87, 0x00, 0x03, 0x0a, 0xea, 0xff, + 0x55, 0x84, 0x00, 0x02, 0x65, 0xff, 0xb7, 0x80, 0x00, 0x00, 0x4f, 0x85, + 0xb9, 0x0b, 0xd4, 0xff, 0xe3, 0xb9, 0xb9, 0x2e, 0x00, 0x00, 0x0c, 0x5b, + 0x75, 0x2a, 0x84, 0x00, 0x02, 0x8f, 0xff, 0x83, 0x81, 0x00, 0x03, 0x2b, + 0xff, 0xff, 0x1b, 0x83, 0x00, 0x02, 0x7e, 0xff, 0x7e, 0x85, 0x00, 0x02, + 0x80, 0xff, 0x7a, 0x86, 0x00, 0x03, 0x0c, 0xff, 0xff, 0x48, 0x84, 0x00, + 0x02, 0x76, 0xff, 0x99, 0x82, 0x00, 0x01, 0x02, 0x0b, 0x83, 0x00, 0x03, + 0x36, 0xff, 0xdd, 0x0b, 0x85, 0x00, 0x00, 0x02, 0x80, 0x09, 0x8b, 0x00, + 0x03, 0x2f, 0x34, 0x34, 0x20, 0x8b, 0x00, 0x07, 0x0f, 0x4a, 0xad, 0xff, + 0xff, 0xa2, 0x41, 0x05, 0x90, 0x00, 0x07, 0x0d, 0x52, 0xbd, 0xff, 0xff, + 0x94, 0x3a, 0x07, 0x8b, 0x00, 0x02, 0x15, 0x1d, 0x12, 0x85, 0x00, 0x15, + 0x1f, 0xff, 0x42, 0x01, 0xad, 0xa3, 0x00, 0x00, 0x05, 0x99, 0xc2, 0x4a, + 0x00, 0x28, 0xff, 0x26, 0x00, 0x00, 0x20, 0xff, 0xff, 0x2f, 0x84, 0x00, + 0x03, 0x50, 0xff, 0xd8, 0x0b, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, + 0x00, 0x03, 0x07, 0xdd, 0xff, 0x62, 0x80, 0x00, 0x03, 0x6d, 0xff, 0xd8, + 0x10, 0x83, 0x00, 0x03, 0x19, 0xea, 0xff, 0x33, 0x80, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x83, 0x00, 0x03, 0x24, 0xff, 0xff, 0x49, 0x81, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x8b, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x22, 0x8a, 0x00, + 0x03, 0x69, 0xff, 0xdd, 0x12, 0x83, 0x00, 0x03, 0x43, 0xff, 0xff, 0x06, + 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, + 0x53, 0x86, 0x00, 0x02, 0xb1, 0xff, 0x69, 0x86, 0x00, 0x03, 0x3f, 0xff, + 0xff, 0x18, 0x81, 0x00, 0x03, 0x20, 0xff, 0xff, 0x30, 0x82, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x81, 0x00, 0x04, 0x03, 0x7f, 0xff, 0xff, 0x2a, 0x83, + 0x00, 0x02, 0x7c, 0xff, 0x98, 0x89, 0x00, 0x02, 0x1d, 0xff, 0xc2, 0x85, + 0x00, 0x03, 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, 0x02, 0x80, 0xff, 0x4d, + 0x81, 0x00, 0x05, 0x68, 0xff, 0x64, 0x6c, 0xff, 0x53, 0x80, 0x00, 0x04, + 0x01, 0xab, 0xff, 0xa2, 0x02, 0x82, 0x00, 0x03, 0x0e, 0xdd, 0xff, 0x65, + 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8a, 0x00, 0x03, 0x12, 0xff, 0xff, + 0x5f, 0x84, 0x00, 0x02, 0x92, 0xff, 0xa6, 0x81, 0x00, 0x02, 0x80, 0xff, + 0x8d, 0x82, 0x00, 0x03, 0x79, 0xff, 0xc4, 0x11, 0x81, 0x00, 0x02, 0x60, + 0xc2, 0x99, 0x85, 0x00, 0x03, 0x1d, 0xff, 0xff, 0x30, 0x85, 0x00, 0x02, + 0xaa, 0xff, 0x69, 0x86, 0x00, 0x02, 0xa3, 0xff, 0x7e, 0x83, 0x00, 0x03, + 0x07, 0xdd, 0xff, 0x5b, 0x84, 0x00, 0x06, 0x68, 0xff, 0x74, 0x01, 0xad, + 0xff, 0x41, 0x84, 0x00, 0x0c, 0x8f, 0xff, 0x29, 0xb1, 0xc4, 0x03, 0x00, + 0x14, 0xff, 0x7b, 0x40, 0xff, 0x5f, 0x82, 0x00, 0x03, 0x34, 0xff, 0xff, + 0x26, 0x80, 0x00, 0x03, 0x46, 0xff, 0xd8, 0x1a, 0x87, 0x00, 0x02, 0xa3, + 0xff, 0x69, 0x86, 0x00, 0x04, 0x09, 0x9d, 0xff, 0x8b, 0x05, 0x8c, 0x00, + 0x03, 0x34, 0xff, 0xff, 0x07, 0x8f, 0x00, 0x02, 0x7b, 0xff, 0x6d, 0x89, + 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0xb6, 0x00, 0x03, 0x1b, 0xff, 0xff, + 0x30, 0x82, 0x00, 0x03, 0x12, 0xff, 0xff, 0x66, 0x82, 0x00, 0x03, 0x40, + 0xff, 0xff, 0x27, 0x82, 0x00, 0x03, 0x02, 0xbf, 0xff, 0x57, 0x81, 0x00, + 0x02, 0x8c, 0xff, 0x7b, 0x84, 0x00, 0x02, 0x5c, 0x66, 0x3e, 0x81, 0x00, + 0x02, 0x8f, 0xff, 0x78, 0x83, 0x00, 0x03, 0x5b, 0xff, 0xff, 0x22, 0x81, + 0x00, 0x02, 0x7e, 0xff, 0x8f, 0x84, 0x00, 0x00, 0x02, 0x86, 0x00, 0x02, + 0x4b, 0xff, 0xb9, 0x88, 0x00, 0x02, 0x84, 0xff, 0x7c, 0x83, 0x00, 0x03, + 0x53, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, + 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x86, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, + 0x8b, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x09, 0x7c, 0xff, + 0x69, 0x00, 0x00, 0x01, 0x76, 0xff, 0xb5, 0x0e, 0x88, 0x00, 0x03, 0x34, + 0xff, 0xff, 0x07, 0x84, 0x00, 0x02, 0x50, 0xff, 0x78, 0x80, 0x00, 0x02, + 0x74, 0xff, 0x50, 0x80, 0x00, 0x02, 0xb1, 0xff, 0x31, 0x80, 0x00, 0x02, + 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x81, 0x00, + 0x02, 0x8d, 0xff, 0x7c, 0x83, 0x00, 0x03, 0x04, 0xbd, 0xff, 0x55, 0x81, + 0x00, 0x03, 0x40, 0xff, 0xff, 0x29, 0x82, 0x00, 0x03, 0x01, 0xb9, 0xff, + 0x58, 0x81, 0x00, 0x02, 0x8d, 0xff, 0x7c, 0x83, 0x00, 0x03, 0x60, 0xff, + 0xff, 0x24, 0x83, 0x00, 0x02, 0xdd, 0xff, 0x43, 0x93, 0x00, 0x02, 0xa0, + 0xff, 0x3f, 0x83, 0x00, 0x03, 0x0d, 0xff, 0xff, 0x2f, 0x88, 0x00, 0x03, + 0x3a, 0xff, 0xff, 0x06, 0x82, 0x00, 0x03, 0x3a, 0xff, 0xff, 0x2d, 0x83, + 0x00, 0x07, 0x02, 0xa8, 0xff, 0x55, 0x01, 0xaa, 0xff, 0x57, 0x84, 0x00, + 0x0c, 0xc2, 0xff, 0x1e, 0xad, 0xbb, 0x03, 0x00, 0x1c, 0xff, 0x5d, 0x4d, + 0xff, 0x6c, 0x83, 0x00, 0x08, 0x36, 0xff, 0xd1, 0x18, 0x00, 0x3f, 0xff, + 0xca, 0x16, 0x86, 0x00, 0x06, 0x55, 0xff, 0x8f, 0x01, 0x9c, 0xff, 0x4b, + 0x85, 0x00, 0x04, 0x03, 0x7d, 0xff, 0x96, 0x08, 0x8c, 0x00, 0x03, 0x63, + 0xff, 0xbd, 0x06, 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x03, + 0x1a, 0xff, 0xff, 0x39, 0x9a, 0x00, 0x02, 0x15, 0x1d, 0x12, 0xbb, 0x00, + 0x01, 0xbd, 0x4d, 0x81, 0x00, 0x02, 0x45, 0xd8, 0x04, 0x83, 0x00, 0x0e, + 0x61, 0xff, 0xb7, 0x0f, 0x00, 0x00, 0x31, 0xff, 0x31, 0x00, 0x00, 0x0e, + 0xb9, 0xff, 0x46, 0x81, 0x00, 0x02, 0x41, 0xff, 0x45, 0x80, 0x00, 0x0b, + 0xbf, 0xff, 0x06, 0x00, 0x00, 0x20, 0xff, 0x71, 0x1b, 0xff, 0xff, 0x1d, + 0x81, 0x00, 0x04, 0x01, 0x6f, 0xff, 0xff, 0x58, 0x96, 0x00, 0x03, 0x06, + 0xea, 0xff, 0x48, 0x8f, 0x00, 0x02, 0x70, 0xff, 0x8b, 0x9a, 0x00, 0x02, + 0x59, 0xff, 0x34, 0x89, 0x00, 0x00, 0x22, 0x80, 0xff, 0x00, 0x1d, 0x9b, + 0x00, 0x00, 0x1b, 0x80, 0xff, 0x87, 0x00, 0x03, 0x41, 0xff, 0xb5, 0x08, + 0x89, 0x00, 0x03, 0x28, 0xff, 0xff, 0x2b, 0x82, 0x00, 0x03, 0x5b, 0xff, + 0xca, 0x09, 0x87, 0x00, 0x02, 0x92, 0xff, 0x5c, 0x85, 0x00, 0x04, 0x02, + 0x77, 0xff, 0xa6, 0x10, 0x89, 0x00, 0x03, 0x7c, 0xff, 0xc7, 0x14, 0x82, + 0x00, 0x03, 0x12, 0xca, 0xff, 0x69, 0x89, 0x00, 0x02, 0x63, 0xff, 0x89, + 0x82, 0x00, 0x04, 0x02, 0xad, 0xff, 0x90, 0x06, 0x82, 0x00, 0x03, 0x32, + 0xff, 0xff, 0x3d, 0x81, 0x00, 0x04, 0x04, 0xab, 0xff, 0x79, 0x01, 0x81, + 0x00, 0x03, 0x20, 0xff, 0xff, 0x3f, 0x84, 0x00, 0x03, 0x04, 0xd8, 0xff, + 0x4c, 0x87, 0x00, 0x03, 0x98, 0xff, 0x91, 0x03, 0x82, 0x00, 0x03, 0x0d, + 0xca, 0xff, 0x5b, 0x81, 0x00, 0x03, 0x40, 0xdd, 0xb9, 0x09, 0x81, 0x00, + 0x03, 0x0d, 0xaa, 0xff, 0x64, 0x86, 0x00, 0x00, 0x1b, 0x80, 0xff, 0x8a, + 0x00, 0x00, 0x0d, 0x80, 0xff, 0x00, 0x2a, 0x8d, 0x00, 0x05, 0x03, 0x30, + 0x80, 0xff, 0xff, 0x17, 0x90, 0x00, 0x04, 0x36, 0xff, 0xdd, 0x6a, 0x22, + 0x99, 0x00, 0x0e, 0x0a, 0xff, 0x60, 0x00, 0x55, 0xff, 0x3d, 0x15, 0x70, + 0x59, 0x8b, 0x6d, 0x1a, 0x9a, 0x80, 0x80, 0x00, 0x03, 0x60, 0xff, 0xbd, + 0x05, 0x84, 0x00, 0x03, 0x17, 0xff, 0xff, 0x3f, 0x80, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x84, 0x00, 0x03, 0x49, 0xff, 0xff, 0x35, 0x80, 0x00, 0x04, + 0x20, 0xff, 0xff, 0x73, 0x02, 0x81, 0x00, 0x04, 0x0b, 0x9a, 0xff, 0x9a, + 0x02, 0x80, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x82, 0x00, 0x04, 0x14, 0xa6, + 0xff, 0xb7, 0x0c, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8b, 0x00, 0x03, + 0x2d, 0xff, 0xff, 0x22, 0x8a, 0x00, 0x04, 0x1e, 0xff, 0xff, 0x78, 0x03, + 0x82, 0x00, 0x03, 0x45, 0xff, 0xff, 0x06, 0x80, 0x00, 0x02, 0x80, 0xff, + 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, 0x86, 0x00, 0x02, 0xb1, + 0xff, 0x69, 0x86, 0x00, 0x03, 0x19, 0xff, 0xff, 0x5c, 0x81, 0x00, 0x03, + 0x58, 0xff, 0xff, 0x11, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x82, 0x00, + 0x04, 0x0d, 0xab, 0xff, 0xbd, 0x12, 0x82, 0x00, 0x02, 0x7c, 0xff, 0x98, + 0x89, 0x00, 0x02, 0x1d, 0xff, 0xc2, 0x85, 0x00, 0x03, 0x17, 0xff, 0xff, + 0x04, 0x80, 0x00, 0x02, 0x80, 0xff, 0x4d, 0x81, 0x00, 0x05, 0x1b, 0xff, + 0xe3, 0x79, 0xff, 0x53, 0x81, 0x00, 0x03, 0x49, 0xff, 0xff, 0x46, 0x82, + 0x00, 0x03, 0x64, 0xff, 0xff, 0x20, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x8b, 0x00, 0x03, 0x90, 0xff, 0xbf, 0x07, 0x82, 0x00, 0x03, 0x19, 0xff, + 0xff, 0x55, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x82, 0x00, 0x03, 0x13, + 0xcd, 0xff, 0x79, 0x81, 0x00, 0x03, 0x48, 0xff, 0xff, 0x3d, 0x84, 0x00, + 0x03, 0x60, 0xff, 0xff, 0x14, 0x85, 0x00, 0x02, 0xaa, 0xff, 0x69, 0x86, + 0x00, 0x03, 0x62, 0xff, 0xe3, 0x15, 0x82, 0x00, 0x03, 0x3f, 0xff, 0xff, + 0x30, 0x84, 0x00, 0x06, 0x26, 0xff, 0xd8, 0x24, 0xff, 0xdd, 0x0c, 0x84, + 0x00, 0x04, 0x66, 0xff, 0x55, 0xff, 0x6e, 0x80, 0x00, 0x04, 0xa2, 0xd1, + 0x57, 0xff, 0x41, 0x81, 0x00, 0x03, 0x10, 0xbf, 0xff, 0x5d, 0x81, 0x00, + 0x04, 0x02, 0x89, 0xff, 0x92, 0x05, 0x86, 0x00, 0x02, 0xa3, 0xff, 0x69, + 0x85, 0x00, 0x04, 0x02, 0x76, 0xff, 0xb5, 0x10, 0x8d, 0x00, 0x03, 0x34, + 0xff, 0xff, 0x07, 0x8f, 0x00, 0x03, 0x1a, 0xea, 0xff, 0x21, 0x88, 0x00, + 0x03, 0x26, 0xff, 0xff, 0x15, 0xb6, 0x00, 0x03, 0x17, 0xff, 0xff, 0x39, + 0x82, 0x00, 0x03, 0x67, 0xff, 0xff, 0x6b, 0x82, 0x00, 0x03, 0x40, 0xff, + 0xff, 0x6d, 0x82, 0x00, 0x03, 0x2b, 0xff, 0xff, 0x28, 0x81, 0x00, 0x03, + 0x3f, 0xff, 0xff, 0x1d, 0x82, 0x00, 0x03, 0x24, 0xff, 0xff, 0x3a, 0x81, + 0x00, 0x03, 0x52, 0xff, 0xdd, 0x10, 0x81, 0x00, 0x04, 0x0c, 0xc2, 0xff, + 0xff, 0x22, 0x81, 0x00, 0x03, 0x34, 0xff, 0xff, 0x2c, 0x82, 0x00, 0x03, + 0x06, 0x9d, 0x7e, 0x1f, 0x84, 0x00, 0x02, 0x4b, 0xff, 0xb9, 0x88, 0x00, + 0x03, 0x4f, 0xff, 0xd8, 0x0d, 0x81, 0x00, 0x04, 0x0d, 0xbd, 0xff, 0xff, + 0x2a, 0x81, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, + 0xff, 0x2d, 0x86, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, 0x8b, 0x00, 0x03, + 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, 0x69, 0x80, 0x00, + 0x04, 0x0d, 0xb1, 0xff, 0x7d, 0x02, 0x87, 0x00, 0x03, 0x34, 0xff, 0xff, + 0x07, 0x84, 0x00, 0x02, 0x50, 0xff, 0x78, 0x80, 0x00, 0x02, 0x74, 0xff, + 0x50, 0x80, 0x00, 0x02, 0xb1, 0xff, 0x31, 0x80, 0x00, 0x02, 0x40, 0xff, + 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x81, 0x00, 0x03, 0x3f, + 0xff, 0xff, 0x1b, 0x82, 0x00, 0x03, 0x38, 0xff, 0xff, 0x1c, 0x81, 0x00, + 0x03, 0x40, 0xff, 0xff, 0x70, 0x82, 0x00, 0x03, 0x28, 0xff, 0xff, 0x2b, + 0x81, 0x00, 0x03, 0x50, 0xff, 0xe3, 0x13, 0x81, 0x00, 0x04, 0x0f, 0xc7, + 0xff, 0xff, 0x24, 0x83, 0x00, 0x02, 0xdd, 0xff, 0x43, 0x89, 0x00, 0x02, + 0x37, 0x8d, 0x5c, 0x83, 0x00, 0x03, 0x01, 0xab, 0xff, 0x32, 0x83, 0x00, + 0x03, 0x0a, 0xff, 0xff, 0x40, 0x88, 0x00, 0x03, 0x2a, 0xff, 0xff, 0x22, + 0x81, 0x00, 0x04, 0x04, 0x96, 0xff, 0xff, 0x2d, 0x84, 0x00, 0x06, 0x49, + 0xff, 0x9d, 0x1d, 0xff, 0xff, 0x18, 0x84, 0x00, 0x0c, 0x82, 0xff, 0x49, + 0xff, 0x63, 0x00, 0x00, 0x01, 0xad, 0xa6, 0x63, 0xff, 0x49, 0x82, 0x00, + 0x0a, 0x16, 0xca, 0xff, 0x3d, 0x00, 0x00, 0x01, 0x75, 0xff, 0x91, 0x05, + 0x85, 0x00, 0x06, 0x14, 0xff, 0xff, 0x45, 0xff, 0xe3, 0x0f, 0x85, 0x00, + 0x03, 0x5c, 0xff, 0xb9, 0x13, 0x8d, 0x00, 0x03, 0x1b, 0xff, 0xff, 0x1b, + 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x03, 0x39, 0xff, 0xd4, + 0x02, 0xbd, 0x00, 0x02, 0x6c, 0x74, 0x46, 0x97, 0x00, 0x02, 0x13, 0xff, + 0x2d, 0x81, 0x00, 0x01, 0x6d, 0x88, 0x84, 0x00, 0x0e, 0x11, 0xbf, 0xff, + 0xa0, 0x2c, 0x02, 0x31, 0xff, 0x31, 0x03, 0x28, 0x95, 0xff, 0xc4, 0x0e, + 0x80, 0x00, 0x03, 0x19, 0xd4, 0x7e, 0x01, 0x80, 0x00, 0x0c, 0x73, 0xff, + 0x28, 0x00, 0x00, 0x4b, 0xff, 0x45, 0x01, 0x8c, 0xff, 0x94, 0x15, 0x80, + 0x00, 0x08, 0x1a, 0x94, 0xff, 0xff, 0xc4, 0x31, 0x02, 0x00, 0x02, 0x93, + 0x00, 0x02, 0x92, 0xff, 0x71, 0x8f, 0x00, 0x02, 0xb3, 0xff, 0x5c, 0x9a, + 0x00, 0x02, 0x59, 0xff, 0x34, 0x89, 0x00, 0x03, 0x4a, 0xff, 0xff, 0x7a, + 0x9c, 0x00, 0x00, 0x1b, 0x80, 0xff, 0x86, 0x00, 0x03, 0x0a, 0xbd, 0xff, + 0x3c, 0x8b, 0x00, 0x0a, 0x76, 0xff, 0xc4, 0x3c, 0x0c, 0x02, 0x13, 0x57, + 0xff, 0xff, 0x3f, 0x88, 0x00, 0x02, 0x92, 0xff, 0x5c, 0x85, 0x00, 0x03, + 0x45, 0xff, 0xff, 0x1f, 0x8a, 0x00, 0x0c, 0x1f, 0xdd, 0xff, 0xb1, 0x3a, + 0x0d, 0x05, 0x12, 0x39, 0xab, 0xff, 0xe3, 0x1b, 0x89, 0x00, 0x02, 0x63, + 0xff, 0x89, 0x83, 0x00, 0x0c, 0x38, 0xff, 0xff, 0x88, 0x25, 0x06, 0x02, + 0x13, 0x58, 0xea, 0xff, 0x8d, 0x05, 0x82, 0x00, 0x0b, 0x2f, 0xff, 0xff, + 0x6f, 0x17, 0x01, 0x07, 0x3a, 0xc7, 0xff, 0xa0, 0x06, 0x84, 0x00, 0x03, + 0x1a, 0xff, 0xff, 0x2e, 0x87, 0x00, 0x04, 0x30, 0xff, 0xff, 0x6f, 0x12, + 0x80, 0x00, 0x04, 0x1a, 0x8a, 0xff, 0xca, 0x14, 0x81, 0x00, 0x0b, 0x11, + 0xd4, 0xff, 0x85, 0x1d, 0x03, 0x04, 0x29, 0x9d, 0xff, 0xb5, 0x0e, 0x86, + 0x00, 0x00, 0x1b, 0x80, 0xff, 0x8a, 0x00, 0x04, 0x30, 0xff, 0xff, 0x91, + 0x01, 0x90, 0x00, 0x02, 0x19, 0x5b, 0x14, 0x90, 0x00, 0x02, 0x2b, 0x4a, + 0x0f, 0x90, 0x00, 0x02, 0x5f, 0x74, 0x54, 0x86, 0x00, 0x13, 0xa3, 0xa2, + 0x00, 0x0b, 0x91, 0xff, 0xff, 0x6f, 0x05, 0x41, 0xff, 0xff, 0x8d, 0x0d, + 0x00, 0x00, 0x07, 0xca, 0xff, 0x5a, 0x86, 0x00, 0x02, 0x87, 0xff, 0x91, + 0x80, 0x00, 0x02, 0x80, 0xff, 0x91, 0x80, 0x09, 0x07, 0x0a, 0x14, 0x29, + 0x6d, 0xff, 0xff, 0x92, 0x05, 0x81, 0x00, 0x0b, 0x56, 0xff, 0xff, 0x85, + 0x2d, 0x13, 0x13, 0x35, 0xaf, 0xff, 0xc4, 0x1a, 0x81, 0x00, 0x0b, 0x80, + 0xff, 0x94, 0x0f, 0x0f, 0x14, 0x23, 0x52, 0xca, 0xff, 0xe3, 0x2a, 0x82, + 0x00, 0x02, 0x80, 0xff, 0x94, 0x87, 0x0f, 0x00, 0x05, 0x80, 0x00, 0x03, + 0x2d, 0xff, 0xff, 0x22, 0x8b, 0x00, 0x0c, 0x56, 0xff, 0xff, 0x88, 0x2d, + 0x13, 0x13, 0x27, 0x5b, 0xd4, 0xff, 0xff, 0x05, 0x80, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, 0x81, 0x00, 0x00, + 0x03, 0x81, 0x0f, 0x02, 0xb5, 0xff, 0x72, 0x81, 0x0f, 0x83, 0x00, 0x09, + 0x78, 0xff, 0xff, 0x56, 0x19, 0x18, 0x4b, 0xea, 0xff, 0x6f, 0x83, 0x00, + 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x04, 0x20, 0xdd, 0xff, 0x8b, 0x05, + 0x81, 0x00, 0x02, 0x7c, 0xff, 0x9d, 0x86, 0x0f, 0x80, 0x00, 0x02, 0x1d, + 0xff, 0xc2, 0x85, 0x00, 0x03, 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, 0x02, + 0x80, 0xff, 0x4d, 0x82, 0x00, 0x04, 0x76, 0xff, 0xea, 0xff, 0x53, 0x81, + 0x00, 0x0b, 0x06, 0x9c, 0xff, 0xff, 0x5b, 0x1c, 0x11, 0x22, 0x6e, 0xff, + 0xff, 0x61, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8b, 0x00, 0x03, 0x35, + 0xff, 0xff, 0x5c, 0x81, 0x00, 0x04, 0x03, 0x7b, 0xff, 0xdd, 0x13, 0x81, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x45, 0xff, 0xff, 0x3a, + 0x80, 0x00, 0x0d, 0x08, 0x9f, 0xff, 0xea, 0x5b, 0x1e, 0x08, 0x04, 0x0e, + 0x28, 0x72, 0xff, 0xff, 0x68, 0x86, 0x00, 0x02, 0xaa, 0xff, 0x69, 0x86, + 0x00, 0x0c, 0x1c, 0xea, 0xff, 0xa2, 0x31, 0x14, 0x0f, 0x1c, 0x4d, 0xe3, + 0xff, 0xa0, 0x04, 0x84, 0x00, 0x05, 0x01, 0xa6, 0xff, 0x8d, 0xff, 0x6e, + 0x85, 0x00, 0x04, 0x47, 0xff, 0xa8, 0xff, 0x3a, 0x80, 0x00, 0x04, 0x5a, + 0xff, 0xa6, 0xff, 0x29, 0x80, 0x00, 0x04, 0x01, 0x7b, 0xff, 0xa5, 0x07, + 0x82, 0x00, 0x03, 0x17, 0xd4, 0xff, 0x53, 0x86, 0x00, 0x02, 0xa3, 0xff, + 0x69, 0x85, 0x00, 0x03, 0x50, 0xff, 0xff, 0x35, 0x87, 0x0f, 0x00, 0x0c, + 0x83, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x90, 0x00, 0x03, 0x60, 0xff, + 0x8a, 0x01, 0x87, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0xb6, 0x00, 0x0d, + 0x02, 0xb5, 0xff, 0x8c, 0x07, 0x00, 0x00, 0x07, 0x5e, 0x8f, 0x6c, 0xff, + 0x98, 0x01, 0x81, 0x00, 0x0c, 0x41, 0xff, 0xd1, 0xb5, 0x49, 0x04, 0x00, + 0x00, 0x1b, 0xab, 0xff, 0x94, 0x02, 0x81, 0x00, 0x0c, 0x04, 0x95, 0xff, + 0xad, 0x2a, 0x03, 0x00, 0x03, 0x2e, 0xb5, 0xff, 0x98, 0x05, 0x81, 0x00, + 0x0c, 0x15, 0xe3, 0xff, 0x89, 0x15, 0x00, 0x00, 0x1b, 0x8c, 0x81, 0xff, + 0xff, 0x22, 0x81, 0x00, 0x0c, 0x03, 0x87, 0xff, 0xc7, 0x32, 0x02, 0x00, + 0x00, 0x1e, 0x87, 0xff, 0xbd, 0x0b, 0x84, 0x00, 0x02, 0x4b, 0xff, 0xb9, + 0x88, 0x00, 0x0c, 0x16, 0xea, 0xff, 0x79, 0x0c, 0x00, 0x00, 0x16, 0x8d, + 0x79, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, + 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x86, 0x00, 0x03, 0x24, 0xff, 0xff, 0x17, + 0x8b, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, 0xff, + 0x69, 0x81, 0x00, 0x03, 0x28, 0xff, 0xff, 0x49, 0x87, 0x00, 0x03, 0x34, + 0xff, 0xff, 0x07, 0x84, 0x00, 0x02, 0x50, 0xff, 0x78, 0x80, 0x00, 0x02, + 0x74, 0xff, 0x50, 0x80, 0x00, 0x02, 0xb1, 0xff, 0x31, 0x80, 0x00, 0x02, + 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x81, 0x00, + 0x0b, 0x06, 0x98, 0xff, 0xa2, 0x1c, 0x00, 0x00, 0x01, 0x2f, 0xc7, 0xff, + 0x67, 0x82, 0x00, 0x0c, 0x40, 0xff, 0xd8, 0xaf, 0x4d, 0x05, 0x00, 0x00, + 0x18, 0xa3, 0xff, 0x9d, 0x03, 0x81, 0x00, 0x0c, 0x14, 0xdd, 0xff, 0x91, + 0x17, 0x00, 0x00, 0x1a, 0x8f, 0x7f, 0xff, 0xff, 0x24, 0x83, 0x00, 0x02, + 0xdd, 0xff, 0x43, 0x89, 0x00, 0x04, 0x26, 0xff, 0xe3, 0x3f, 0x05, 0x80, + 0x00, 0x04, 0x0d, 0x62, 0xff, 0xbb, 0x09, 0x84, 0x00, 0x08, 0xaf, 0xff, + 0xa8, 0x23, 0x08, 0x06, 0x0f, 0x1f, 0x31, 0x82, 0x00, 0x0c, 0x0b, 0xd8, + 0xff, 0x8a, 0x11, 0x00, 0x00, 0x15, 0x78, 0x79, 0xff, 0xff, 0x2d, 0x84, + 0x00, 0x05, 0x10, 0xea, 0xff, 0x69, 0xff, 0x82, 0x85, 0x00, 0x04, 0x5b, + 0xff, 0x98, 0xff, 0x2d, 0x80, 0x00, 0x04, 0x5c, 0xff, 0x9d, 0xff, 0x2e, + 0x81, 0x00, 0x03, 0x05, 0x90, 0xff, 0x71, 0x81, 0x00, 0x03, 0x0d, 0xb3, + 0xff, 0x5d, 0x86, 0x00, 0x04, 0x74, 0xff, 0xdd, 0xff, 0x6d, 0x85, 0x00, + 0x03, 0x3e, 0xff, 0xdd, 0x24, 0x8e, 0x00, 0x03, 0x11, 0xff, 0xff, 0x1f, + 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x3d, 0xff, 0xb1, + 0x9b, 0x00, 0x02, 0x5f, 0x74, 0x54, 0x9d, 0x00, 0x02, 0xc2, 0xff, 0x69, + 0x97, 0x00, 0x02, 0x2e, 0xff, 0x11, 0x81, 0x00, 0x01, 0xab, 0x57, 0x85, + 0x00, 0x0c, 0x20, 0xb3, 0xff, 0xff, 0xcd, 0xb7, 0xff, 0xbd, 0xe3, 0xff, + 0xff, 0xb7, 0x23, 0x80, 0x00, 0x03, 0x05, 0x94, 0xbd, 0x10, 0x81, 0x00, + 0x18, 0x20, 0xea, 0xab, 0x3e, 0x49, 0xd4, 0xb3, 0x0c, 0x00, 0x15, 0xaa, + 0xff, 0xd8, 0x7d, 0x6b, 0x8c, 0xff, 0xff, 0x60, 0x68, 0xff, 0xff, 0xc4, + 0xc2, 0x19, 0x93, 0x00, 0x03, 0x55, 0xff, 0xbf, 0x03, 0x8d, 0x00, 0x03, + 0x17, 0xff, 0xff, 0x32, 0xa9, 0x00, 0x03, 0x81, 0xff, 0xff, 0x24, 0x9c, + 0x00, 0x00, 0x1b, 0x80, 0xff, 0x86, 0x00, 0x03, 0x57, 0xff, 0x98, 0x03, + 0x8b, 0x00, 0x01, 0x0a, 0x87, 0x84, 0xff, 0x01, 0x55, 0x01, 0x82, 0x00, + 0x00, 0x8f, 0x82, 0xcd, 0x02, 0xea, 0xff, 0xe3, 0x81, 0xcd, 0x06, 0x3b, + 0x00, 0x00, 0x02, 0xc7, 0xff, 0xff, 0x86, 0xdd, 0x00, 0x89, 0x82, 0x00, + 0x01, 0x2f, 0xc7, 0x84, 0xff, 0x01, 0xc7, 0x30, 0x8a, 0x00, 0x02, 0x63, + 0xff, 0x89, 0x84, 0x00, 0x01, 0x4b, 0xea, 0x84, 0xff, 0x01, 0x82, 0x0d, + 0x84, 0x00, 0x04, 0x41, 0xe3, 0xff, 0xff, 0xe3, 0x80, 0xff, 0x01, 0xa2, + 0x17, 0x85, 0x00, 0x03, 0x2a, 0xff, 0xff, 0x1f, 0x88, 0x00, 0x0a, 0x43, + 0xdd, 0xff, 0xff, 0xa8, 0x92, 0xb1, 0xff, 0xff, 0xbb, 0x26, 0x83, 0x00, + 0x04, 0x34, 0xe3, 0xff, 0xff, 0xea, 0x80, 0xff, 0x01, 0xa8, 0x19, 0x87, + 0x00, 0x00, 0x1b, 0x80, 0xff, 0x8a, 0x00, 0x03, 0x5b, 0xff, 0xff, 0x31, + 0xbd, 0x00, 0x02, 0x9d, 0xff, 0x84, 0x86, 0x00, 0x06, 0x53, 0xff, 0x1d, + 0x00, 0x02, 0x1c, 0x14, 0x80, 0x00, 0x02, 0x16, 0x1a, 0x02, 0x80, 0x00, + 0x03, 0x38, 0xff, 0xff, 0x1e, 0x86, 0x00, 0x06, 0x39, 0xff, 0xff, 0x1c, + 0x00, 0x00, 0x80, 0x87, 0xff, 0x01, 0x85, 0x0f, 0x82, 0x00, 0x02, 0x01, + 0x55, 0xea, 0x83, 0xff, 0x01, 0xbb, 0x24, 0x82, 0x00, 0x00, 0x80, 0x85, + 0xff, 0x01, 0xb1, 0x28, 0x83, 0x00, 0x00, 0x80, 0x89, 0xff, 0x00, 0x2d, + 0x80, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x22, 0x8b, 0x00, 0x01, 0x01, 0x5a, + 0x85, 0xff, 0x01, 0x88, 0x21, 0x81, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, + 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, 0x81, 0x00, 0x00, 0x1d, 0x88, 0xff, + 0x00, 0x02, 0x82, 0x00, 0x01, 0x10, 0xa2, 0x83, 0xff, 0x01, 0x99, 0x0d, + 0x83, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x84, 0x00, 0x03, 0x3e, 0xff, 0xff, + 0x5c, 0x81, 0x00, 0x00, 0x7c, 0x88, 0xff, 0x05, 0x06, 0x00, 0x00, 0x1d, + 0xff, 0xc2, 0x85, 0x00, 0x03, 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, 0x02, + 0x80, 0xff, 0x4d, 0x82, 0x00, 0x00, 0x22, 0x80, 0xff, 0x00, 0x53, 0x82, + 0x00, 0x01, 0x11, 0x96, 0x84, 0xff, 0x01, 0x6a, 0x04, 0x82, 0x00, 0x02, + 0x80, 0xff, 0x8d, 0x8b, 0x00, 0x0b, 0x02, 0x7c, 0xff, 0xff, 0x6f, 0x26, + 0x19, 0x2d, 0x82, 0xff, 0xff, 0x47, 0x82, 0x00, 0x02, 0x80, 0xff, 0x8d, + 0x83, 0x00, 0x04, 0x03, 0x91, 0xff, 0xc4, 0x10, 0x80, 0x00, 0x01, 0x12, + 0x90, 0x86, 0xff, 0x01, 0x6c, 0x06, 0x86, 0x00, 0x02, 0xaa, 0xff, 0x69, + 0x87, 0x00, 0x01, 0x3f, 0xea, 0x84, 0xff, 0x01, 0xad, 0x1a, 0x86, 0x00, + 0x00, 0x4b, 0x80, 0xff, 0x00, 0x2a, 0x85, 0x00, 0x00, 0x2e, 0x80, 0xff, + 0x00, 0x12, 0x80, 0x00, 0x00, 0x2b, 0x80, 0xff, 0x00, 0x13, 0x80, 0x00, + 0x03, 0x3f, 0xff, 0xff, 0x26, 0x84, 0x00, 0x03, 0x44, 0xff, 0xea, 0x23, + 0x85, 0x00, 0x02, 0xa3, 0xff, 0x69, 0x85, 0x00, 0x8b, 0xff, 0x00, 0x84, + 0x83, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x90, 0x00, 0x03, 0x0f, 0xca, + 0xff, 0x34, 0x87, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0xb7, 0x00, 0x0d, + 0x38, 0xff, 0xff, 0xad, 0x6c, 0x74, 0xc7, 0xa2, 0x13, 0x38, 0xff, 0xff, + 0x87, 0x55, 0x80, 0x00, 0x0b, 0x44, 0xff, 0xb1, 0x2a, 0xd8, 0xc4, 0x8c, + 0x9a, 0xff, 0xff, 0xbf, 0x1a, 0x83, 0x00, 0x0a, 0x0f, 0x91, 0xff, 0xff, + 0xd4, 0xad, 0xe3, 0xff, 0xff, 0x94, 0x11, 0x83, 0x00, 0x00, 0x42, 0x80, + 0xff, 0x07, 0xb3, 0xbd, 0xff, 0x99, 0x1a, 0xff, 0xff, 0x22, 0x82, 0x00, + 0x0a, 0x0e, 0x8c, 0xff, 0xff, 0xbf, 0x95, 0xbd, 0xff, 0xff, 0xb1, 0x1f, + 0x85, 0x00, 0x02, 0x4b, 0xff, 0xb9, 0x89, 0x00, 0x0b, 0x48, 0xff, 0xff, + 0xdd, 0x95, 0x9c, 0xff, 0x85, 0x18, 0xff, 0xff, 0x2a, 0x81, 0x00, 0x02, + 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x80, 0x00, + 0x00, 0x05, 0x82, 0xb9, 0x03, 0xc2, 0xff, 0xff, 0xbf, 0x81, 0xb9, 0x00, + 0x2e, 0x86, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, 0x02, 0x7c, + 0xff, 0x69, 0x82, 0x00, 0x03, 0x54, 0xff, 0xea, 0x22, 0x80, 0x00, 0x00, + 0x14, 0x82, 0xb9, 0x03, 0xc7, 0xff, 0xff, 0xbb, 0x81, 0xb9, 0x05, 0x1f, + 0x00, 0x00, 0x50, 0xff, 0x78, 0x80, 0x00, 0x02, 0x74, 0xff, 0x50, 0x80, + 0x00, 0x02, 0xb1, 0xff, 0x31, 0x80, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, + 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x82, 0x00, 0x0a, 0x13, 0x9c, 0xff, + 0xff, 0xa3, 0x8a, 0xb7, 0xff, 0xff, 0x75, 0x06, 0x82, 0x00, 0x0b, 0x40, + 0xff, 0xd8, 0x2a, 0xdd, 0xca, 0x8c, 0x99, 0xff, 0xff, 0xc4, 0x1c, 0x83, + 0x00, 0x00, 0x40, 0x80, 0xff, 0x07, 0xb5, 0xbd, 0xff, 0x90, 0x22, 0xff, + 0xff, 0x24, 0x83, 0x00, 0x02, 0xdd, 0xff, 0x43, 0x8a, 0x00, 0x0a, 0x52, + 0xff, 0xff, 0xd8, 0x99, 0x8c, 0xa2, 0xea, 0xff, 0xc4, 0x25, 0x85, 0x00, + 0x00, 0x40, 0x84, 0xff, 0x00, 0xaa, 0x83, 0x00, 0x00, 0x4d, 0x80, 0xff, + 0x07, 0xb1, 0xb5, 0xff, 0x9d, 0x0f, 0xd8, 0xff, 0x2f, 0x85, 0x00, 0x00, + 0x74, 0x80, 0xff, 0x00, 0x32, 0x85, 0x00, 0x04, 0x3d, 0xff, 0xff, 0xd1, + 0x06, 0x80, 0x00, 0x00, 0x2a, 0x80, 0xff, 0x00, 0x16, 0x81, 0x00, 0x03, + 0x5b, 0xff, 0xad, 0x0b, 0x82, 0x00, 0x03, 0x29, 0xff, 0xff, 0x31, 0x85, + 0x00, 0x00, 0x27, 0x80, 0xff, 0x00, 0x25, 0x85, 0x00, 0x02, 0xd1, 0xff, + 0xd4, 0x86, 0xa3, 0x00, 0x4c, 0x85, 0x00, 0x03, 0x11, 0xff, 0xff, 0x1f, + 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x3d, 0xff, 0xb1, + 0x9b, 0x00, 0x02, 0x9d, 0xff, 0x84, 0x9d, 0x00, 0x02, 0xc2, 0xff, 0x69, + 0x97, 0x00, 0x01, 0x4f, 0xb9, 0x81, 0x00, 0x02, 0x0e, 0xff, 0x33, 0x86, + 0x00, 0x0a, 0x0a, 0x44, 0x7f, 0xb7, 0xe3, 0xff, 0xe3, 0xb5, 0x7f, 0x45, + 0x0b, 0x81, 0x00, 0x02, 0x57, 0xff, 0x30, 0x83, 0x00, 0x05, 0x26, 0x7c, + 0xb9, 0xaa, 0x6d, 0x16, 0x80, 0x00, 0x0e, 0x09, 0x47, 0x87, 0xbd, 0xd1, + 0xa0, 0x5f, 0x1e, 0x00, 0x01, 0x35, 0x87, 0xcd, 0xa8, 0x12, 0x93, 0x00, + 0x03, 0x22, 0xff, 0xff, 0x27, 0x8d, 0x00, 0x03, 0x49, 0xff, 0xd8, 0x09, + 0xa8, 0x00, 0x03, 0x06, 0xdd, 0xff, 0x88, 0x9d, 0x00, 0x00, 0x1b, 0x80, + 0xff, 0x85, 0x00, 0x03, 0x15, 0xdd, 0xff, 0x2a, 0x8d, 0x00, 0x07, 0x03, + 0x37, 0x79, 0xb5, 0xd4, 0xa5, 0x66, 0x22, 0x84, 0x00, 0x00, 0x98, 0x89, + 0xff, 0x03, 0x3d, 0x00, 0x00, 0x04, 0x89, 0xff, 0x00, 0x8d, 0x83, 0x00, + 0x08, 0x0d, 0x49, 0x84, 0xb7, 0xdd, 0xb7, 0x84, 0x4b, 0x0f, 0x8b, 0x00, + 0x02, 0x63, 0xff, 0x89, 0x85, 0x00, 0x08, 0x1a, 0x5b, 0x95, 0xc7, 0xd1, + 0xa6, 0x6b, 0x2e, 0x01, 0x86, 0x00, 0x07, 0x1a, 0x5d, 0x9d, 0xcd, 0xbb, + 0x83, 0x41, 0x06, 0x86, 0x00, 0x03, 0x34, 0xff, 0xff, 0x17, 0x89, 0x00, + 0x08, 0x15, 0x54, 0x8c, 0xbd, 0xdd, 0xb5, 0x81, 0x47, 0x0c, 0x85, 0x00, + 0x07, 0x19, 0x5d, 0x98, 0xc4, 0xbb, 0x87, 0x45, 0x07, 0x88, 0x00, 0x00, + 0x1b, 0x80, 0xff, 0x8a, 0x00, 0x03, 0x9d, 0xff, 0xa0, 0x02, 0xbd, 0x00, + 0x02, 0x9d, 0xff, 0x84, 0x86, 0x00, 0x02, 0x1a, 0xff, 0x6f, 0x8a, 0x00, + 0x02, 0x87, 0xff, 0x9a, 0x87, 0x00, 0x06, 0x09, 0xd1, 0xff, 0x58, 0x00, + 0x00, 0x80, 0x83, 0xff, 0x04, 0xc4, 0x95, 0x62, 0x2a, 0x01, 0x85, 0x00, + 0x07, 0x1c, 0x59, 0x96, 0xc2, 0xc7, 0x91, 0x4e, 0x0d, 0x83, 0x00, 0x00, + 0x80, 0x81, 0xff, 0x04, 0xd4, 0xa6, 0x74, 0x3c, 0x06, 0x84, 0x00, 0x00, + 0x80, 0x89, 0xff, 0x00, 0x2d, 0x80, 0x00, 0x03, 0x2d, 0xff, 0xff, 0x22, + 0x8d, 0x00, 0x07, 0x21, 0x62, 0x9f, 0xcd, 0xb3, 0x89, 0x53, 0x21, 0x83, + 0x00, 0x02, 0x80, 0xff, 0x8d, 0x83, 0x00, 0x03, 0x04, 0xff, 0xff, 0x53, + 0x81, 0x00, 0x00, 0x1d, 0x88, 0xff, 0x00, 0x02, 0x83, 0x00, 0x07, 0x09, + 0x4b, 0x91, 0xcd, 0xc7, 0x8d, 0x47, 0x07, 0x84, 0x00, 0x02, 0x80, 0xff, + 0x8d, 0x85, 0x00, 0x03, 0x65, 0xff, 0xff, 0x34, 0x80, 0x00, 0x00, 0x7c, + 0x88, 0xff, 0x05, 0x06, 0x00, 0x00, 0x1d, 0xff, 0xc2, 0x85, 0x00, 0x03, + 0x17, 0xff, 0xff, 0x04, 0x80, 0x00, 0x02, 0x80, 0xff, 0x4d, 0x83, 0x00, + 0x03, 0x84, 0xff, 0xff, 0x53, 0x83, 0x00, 0x07, 0x04, 0x3c, 0x7c, 0xb1, + 0xd4, 0xa6, 0x69, 0x29, 0x84, 0x00, 0x02, 0x80, 0xff, 0x8d, 0x8c, 0x00, + 0x01, 0x09, 0x7a, 0x83, 0xff, 0x01, 0xea, 0x4f, 0x83, 0x00, 0x02, 0x80, + 0xff, 0x8d, 0x84, 0x00, 0x03, 0x1e, 0xea, 0xff, 0x78, 0x81, 0x00, 0x09, + 0x02, 0x30, 0x68, 0x9a, 0xc7, 0xdd, 0xbb, 0x8c, 0x5b, 0x21, 0x88, 0x00, + 0x02, 0xaa, 0xff, 0x69, 0x88, 0x00, 0x08, 0x1c, 0x5d, 0x95, 0xc4, 0xd8, + 0xb3, 0x7f, 0x45, 0x0b, 0x87, 0x00, 0x04, 0x12, 0xff, 0xff, 0xaf, 0x02, + 0x85, 0x00, 0x03, 0x18, 0xff, 0xff, 0x9c, 0x81, 0x00, 0x0a, 0x08, 0xe3, + 0xff, 0xd8, 0x02, 0x00, 0x00, 0x16, 0xd1, 0xff, 0x5d, 0x85, 0x00, 0x04, + 0x02, 0x85, 0xff, 0xa5, 0x08, 0x84, 0x00, 0x02, 0xa3, 0xff, 0x69, 0x85, + 0x00, 0x8b, 0xff, 0x00, 0x84, 0x83, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, + 0x91, 0x00, 0x03, 0x4a, 0xff, 0xa8, 0x06, 0x86, 0x00, 0x03, 0x26, 0xff, + 0xff, 0x15, 0xb8, 0x00, 0x0c, 0x2d, 0x80, 0xc4, 0xc2, 0x90, 0x4b, 0x0b, + 0x00, 0x03, 0x5a, 0xb3, 0xd1, 0x75, 0x80, 0x00, 0x0a, 0x4a, 0xff, 0x9a, + 0x00, 0x1a, 0x64, 0xa6, 0xd1, 0xa6, 0x5e, 0x11, 0x85, 0x00, 0x08, 0x03, + 0x37, 0x74, 0xaa, 0xd4, 0xb9, 0x7c, 0x3a, 0x04, 0x85, 0x00, 0x0a, 0x28, + 0x76, 0xb7, 0xca, 0x98, 0x4f, 0x09, 0x07, 0xff, 0xff, 0x26, 0x83, 0x00, + 0x08, 0x03, 0x37, 0x76, 0xaf, 0xd8, 0xb9, 0x81, 0x43, 0x08, 0x86, 0x00, + 0x02, 0x4b, 0xff, 0xb9, 0x8a, 0x00, 0x0a, 0x2e, 0x7d, 0xbb, 0xc2, 0x8a, + 0x41, 0x06, 0x0f, 0xff, 0xff, 0x29, 0x81, 0x00, 0x02, 0x40, 0xff, 0xdd, + 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, 0x2d, 0x80, 0x00, 0x00, 0x06, 0x8a, + 0xff, 0x00, 0x31, 0x86, 0x00, 0x03, 0x04, 0xff, 0xff, 0x3b, 0x85, 0x00, + 0x02, 0x7c, 0xff, 0x69, 0x82, 0x00, 0x07, 0x04, 0x8c, 0xff, 0xaa, 0x0b, + 0x00, 0x00, 0x15, 0x8a, 0xff, 0x05, 0x22, 0x00, 0x00, 0x50, 0xff, 0x78, + 0x80, 0x00, 0x02, 0x74, 0xff, 0x50, 0x80, 0x00, 0x02, 0xb1, 0xff, 0x31, + 0x80, 0x00, 0x02, 0x40, 0xff, 0xdd, 0x83, 0x00, 0x03, 0x0f, 0xff, 0xff, + 0x2d, 0x83, 0x00, 0x08, 0x06, 0x3f, 0x7f, 0xb7, 0xd4, 0xaa, 0x6f, 0x2e, + 0x01, 0x83, 0x00, 0x0a, 0x40, 0xff, 0xe3, 0x00, 0x1c, 0x67, 0xaa, 0xd4, + 0xa8, 0x60, 0x13, 0x85, 0x00, 0x0a, 0x27, 0x75, 0xb7, 0xca, 0x98, 0x4c, + 0x08, 0x19, 0xff, 0xff, 0x24, 0x83, 0x00, 0x02, 0xdd, 0xff, 0x43, 0x8b, + 0x00, 0x08, 0x23, 0x63, 0x99, 0xc7, 0xe3, 0xbb, 0x87, 0x4b, 0x0e, 0x87, + 0x00, 0x07, 0x32, 0x7f, 0xbf, 0xdd, 0xbd, 0x91, 0x68, 0x3b, 0x84, 0x00, + 0x0a, 0x36, 0x83, 0xc2, 0xca, 0x95, 0x4d, 0x0a, 0x00, 0xb5, 0xff, 0x33, + 0x85, 0x00, 0x04, 0x2c, 0xff, 0xff, 0xb9, 0x05, 0x85, 0x00, 0x03, 0x24, + 0xff, 0xff, 0x70, 0x81, 0x00, 0x04, 0x06, 0xd1, 0xff, 0xd8, 0x03, 0x80, + 0x00, 0x03, 0x2d, 0xff, 0xff, 0x26, 0x84, 0x00, 0x03, 0x58, 0xff, 0xc2, + 0x13, 0x84, 0x00, 0x04, 0x01, 0x99, 0xff, 0x9a, 0x01, 0x85, 0x00, 0x00, + 0xdd, 0x88, 0xff, 0x00, 0x59, 0x85, 0x00, 0x03, 0x11, 0xff, 0xff, 0x1f, + 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x3d, 0xff, 0xb1, + 0x9b, 0x00, 0x02, 0x9d, 0xff, 0x84, 0xd0, 0x00, 0x02, 0x31, 0xff, 0x31, + 0xbc, 0x00, 0x03, 0x01, 0x98, 0xff, 0x6f, 0x8c, 0x00, 0x03, 0x03, 0xaa, + 0xff, 0x65, 0xa9, 0x00, 0x03, 0x26, 0xff, 0xff, 0x2c, 0xff, 0x00, 0xf7, + 0x00, 0x03, 0x11, 0xff, 0xff, 0x3a, 0xcb, 0x00, 0x02, 0x68, 0xff, 0x37, + 0x84, 0x00, 0x01, 0x2a, 0x5f, 0xff, 0x00, 0xff, 0x00, 0x90, 0x00, 0x07, + 0x01, 0x2c, 0x68, 0xab, 0xff, 0xff, 0x68, 0x1b, 0xff, 0x00, 0x9e, 0x00, + 0x03, 0x34, 0xff, 0xff, 0x07, 0x9e, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, + 0xff, 0x00, 0xa4, 0x00, 0x03, 0x14, 0xff, 0xff, 0x23, 0xa9, 0x00, 0x03, + 0x05, 0xff, 0xff, 0x38, 0xd9, 0x00, 0x02, 0x40, 0xff, 0xff, 0x94, 0x00, + 0x03, 0x19, 0xff, 0xff, 0x24, 0xfd, 0x00, 0x02, 0x99, 0xff, 0x40, 0x9b, + 0x00, 0x03, 0x11, 0xff, 0xff, 0x1f, 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, + 0x8b, 0x00, 0x02, 0x3d, 0xff, 0xb1, 0xf1, 0x00, 0x02, 0x31, 0xff, 0x31, + 0xbd, 0x00, 0x03, 0x36, 0xff, 0xea, 0x17, 0x8b, 0x00, 0x03, 0x34, 0xff, + 0xff, 0x1b, 0xa9, 0x00, 0x03, 0x4f, 0xff, 0x96, 0x01, 0xff, 0x00, 0xf7, + 0x00, 0x03, 0x34, 0xff, 0xad, 0x05, 0xcb, 0x00, 0x04, 0x0c, 0xa2, 0xe3, + 0x43, 0x04, 0x80, 0x00, 0x04, 0x0c, 0x58, 0xff, 0x98, 0x0a, 0xff, 0x00, + 0xff, 0x00, 0x92, 0x00, 0x03, 0x20, 0xff, 0xff, 0x4d, 0xff, 0x00, 0x9f, + 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x9e, 0x00, 0x03, 0x26, 0xff, 0xff, + 0x15, 0x93, 0x00, 0x8d, 0x07, 0x00, 0x06, 0xff, 0x00, 0x03, 0x26, 0xff, + 0xff, 0x13, 0xa9, 0x00, 0x03, 0x14, 0xff, 0xff, 0x2c, 0xd9, 0x00, 0x02, + 0x40, 0xff, 0xff, 0x94, 0x00, 0x03, 0x19, 0xff, 0xff, 0x24, 0xfc, 0x00, + 0x03, 0x29, 0xff, 0xcd, 0x0b, 0x9b, 0x00, 0x03, 0x11, 0xff, 0xff, 0x21, + 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, 0x00, 0x02, 0x40, 0xff, 0xaf, + 0xff, 0x00, 0xb2, 0x00, 0x03, 0x02, 0x92, 0xff, 0x72, 0x8a, 0x00, 0x03, + 0x06, 0xa8, 0xff, 0x66, 0xaa, 0x00, 0x02, 0x89, 0xff, 0x34, 0xff, 0x00, + 0xf8, 0x00, 0x02, 0x62, 0xff, 0x42, 0xcd, 0x00, 0x0a, 0x14, 0x91, 0xff, + 0xb3, 0x6d, 0x60, 0x7d, 0xdd, 0xff, 0x5d, 0x08, 0xff, 0x00, 0xff, 0x00, + 0x94, 0x00, 0x03, 0x94, 0xff, 0xbd, 0x12, 0xff, 0x00, 0x9e, 0x00, 0x03, + 0x34, 0xff, 0xff, 0x07, 0x9e, 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x92, + 0x00, 0x00, 0x07, 0x8d, 0xff, 0x00, 0x98, 0xf7, 0x00, 0x02, 0x68, 0x9a, + 0x5f, 0x82, 0x00, 0x02, 0x5f, 0xff, 0xa8, 0xaa, 0x00, 0x03, 0x52, 0xff, + 0xea, 0x0e, 0xd9, 0x00, 0x02, 0x40, 0xff, 0xff, 0x94, 0x00, 0x03, 0x19, + 0xff, 0xff, 0x24, 0xfb, 0x00, 0x03, 0x06, 0x90, 0xff, 0x58, 0x9c, 0x00, + 0x03, 0x0a, 0xff, 0xff, 0x32, 0x8b, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x8b, + 0x00, 0x02, 0x55, 0xff, 0x99, 0xff, 0x00, 0xb3, 0x00, 0x03, 0x20, 0xea, + 0xff, 0x2e, 0x89, 0x00, 0x03, 0x52, 0xff, 0xbb, 0x0e, 0xa9, 0x00, 0x03, + 0x09, 0xea, 0xa5, 0x03, 0xff, 0x00, 0xf8, 0x00, 0x02, 0xaa, 0xbd, 0x07, + 0xce, 0x00, 0x07, 0x05, 0x3a, 0x80, 0xb5, 0xc2, 0x90, 0x56, 0x19, 0xff, + 0x00, 0xff, 0x00, 0x96, 0x00, 0x07, 0x2a, 0xff, 0xff, 0x9d, 0x2a, 0x08, + 0x04, 0x08, 0xff, 0x00, 0x9a, 0x00, 0x03, 0x34, 0xff, 0xff, 0x07, 0x9e, + 0x00, 0x03, 0x26, 0xff, 0xff, 0x15, 0x92, 0x00, 0x00, 0x02, 0x8d, 0x1f, + 0x00, 0x1b, 0xf7, 0x00, 0x0a, 0x56, 0xff, 0xea, 0x3c, 0x03, 0x00, 0x03, + 0x3d, 0xff, 0xff, 0x41, 0xa3, 0x00, 0x09, 0x17, 0x28, 0x13, 0x08, 0x07, + 0x18, 0x5c, 0xff, 0xff, 0x64, 0xda, 0x00, 0x02, 0x40, 0xff, 0xff, 0x94, + 0x00, 0x03, 0x19, 0xff, 0xff, 0x24, 0xfa, 0x00, 0x04, 0x14, 0x7c, 0xff, + 0xb7, 0x0c, 0x9d, 0x00, 0x03, 0x8f, 0xff, 0x89, 0x0d, 0x8a, 0x00, 0x02, + 0x74, 0xff, 0x4b, 0x8a, 0x00, 0x03, 0x19, 0xb9, 0xff, 0x5c, 0xff, 0x00, + 0xb4, 0x00, 0x03, 0x50, 0xff, 0xb3, 0x0d, 0x87, 0x00, 0x03, 0x21, 0xea, + 0xff, 0x30, 0xaa, 0x00, 0x02, 0x2a, 0xff, 0x3d, 0xff, 0x00, 0xf8, 0x00, + 0x02, 0x07, 0x53, 0x30, 0xff, 0x00, 0xff, 0x00, 0xf1, 0x00, 0x00, 0x4d, + 0x82, 0xff, 0x00, 0x4d, 0xff, 0x00, 0x9a, 0x00, 0x03, 0x34, 0xff, 0xff, + 0xa5, 0x81, 0xa3, 0x00, 0x08, 0x94, 0x00, 0x00, 0x23, 0x81, 0xa3, 0x03, + 0xb1, 0xff, 0xff, 0x15, 0xff, 0x00, 0x9c, 0x00, 0x0a, 0x09, 0x8c, 0xff, + 0xff, 0xc7, 0x9f, 0xdd, 0xff, 0xff, 0x6e, 0x02, 0xa3, 0x00, 0x00, 0x36, + 0x84, 0xff, 0x01, 0x87, 0x08, 0xda, 0x00, 0x02, 0x40, 0xff, 0xff, 0x94, + 0x00, 0x03, 0x19, 0xff, 0xff, 0x24, 0xf8, 0x00, 0x05, 0x62, 0xb7, 0xff, + 0xff, 0xd1, 0x25, 0x9e, 0x00, 0x07, 0x1f, 0xe3, 0xff, 0xff, 0xab, 0xa3, + 0xa3, 0x3c, 0x86, 0x00, 0x02, 0x74, 0xff, 0x4b, 0x86, 0x00, 0x07, 0x5f, + 0xa3, 0xa3, 0xb7, 0xff, 0xff, 0xb7, 0x11, 0xff, 0x00, 0xb4, 0x00, 0x04, + 0x03, 0x80, 0xff, 0x7f, 0x02, 0x85, 0x00, 0x03, 0x0d, 0xad, 0xff, 0x58, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x9d, 0x00, + 0x05, 0x26, 0x6f, 0xa2, 0xad, 0x8d, 0x32, 0xff, 0x00, 0x9a, 0x00, 0x00, + 0x34, 0x84, 0xff, 0x00, 0x09, 0x94, 0x00, 0x00, 0x28, 0x84, 0xff, 0x00, + 0x15, 0xff, 0x00, 0x9d, 0x00, 0x08, 0x04, 0x37, 0x83, 0xbd, 0xdd, 0xb1, + 0x74, 0x31, 0x01, 0xa4, 0x00, 0x08, 0x17, 0x63, 0x92, 0xbf, 0xe3, 0xb7, + 0x7c, 0x3a, 0x03, 0xdb, 0x00, 0x02, 0x40, 0xff, 0xff, 0x94, 0x00, 0x03, + 0x19, 0xff, 0xff, 0x24, 0xf8, 0x00, 0x04, 0x62, 0xff, 0xbf, 0x70, 0x1a, + 0xa0, 0x00, 0x02, 0x22, 0x7c, 0xca, 0x80, 0xff, 0x00, 0x45, 0x86, 0x00, + 0x02, 0x74, 0xff, 0x4b, 0x86, 0x00, 0x00, 0x70, 0x80, 0xff, 0x02, 0xbb, + 0x68, 0x13, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, + 0xff, 0x00, 0xef, 0x00, +}; +static EG_EMBEDDED_IMAGE egemb_font_large = { 1632, 28, EG_EIPIXELMODE_ALPHA, EG_EICOMPMODE_RLE, egemb_liberation_mono_regular_28_data, 17128 }; diff -Nru refind-0.10.4/libeg/libeg.h refind-0.11.2/libeg/libeg.h --- refind-0.10.4/libeg/libeg.h 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/libeg/libeg.h 2017-08-04 13:13:20.000000000 +0000 @@ -53,6 +53,10 @@ UINT8 b, g, r, a; } EG_PIXEL; +// Some colors for EG_IMAGE +#define COLOR_LIGHTBLUE {255, 175, 100, 0} +#define COLOR_RED {0, 0, 200, 0} + typedef struct { UINTN Width; UINTN Height; @@ -138,8 +142,9 @@ IN UINTN AreaPosX, IN UINTN AreaPosY, IN UINTN AreaWidth, IN UINTN AreaHeight, IN UINTN ScreenPosX, IN UINTN ScreenPosY); -VOID egDisplayMessage(IN CHAR16 *Text, EG_PIXEL *BGColor); +VOID egDisplayMessage(IN CHAR16 *Text, EG_PIXEL *BGColor, UINTN PositionCode); EG_IMAGE * egCopyScreen(VOID); +EG_IMAGE * egCopyScreenArea(UINTN XPos, UINTN YPos, UINTN Width, UINTN Height); VOID egScreenShot(VOID); BOOLEAN egSetTextMode(UINT32 RequestedMode); diff -Nru refind-0.10.4/libeg/lodepng.c refind-0.11.2/libeg/lodepng.c --- refind-0.10.4/libeg/lodepng.c 2015-12-07 22:01:06.000000000 +0000 +++ refind-0.11.2/libeg/lodepng.c 2017-05-29 00:02:24.000000000 +0000 @@ -1,7 +1,7 @@ /* -LodePNG version 20151024 +LodePNG version 20161127 -Copyright (c) 2005-2015 Lode Vandevenne +Copyright (c) 2005-2016 Lode Vandevenne This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -30,19 +30,16 @@ #include "lodepng.h" +#include #include #include -#ifdef LODEPNG_COMPILE_CPP -#include -#endif /*LODEPNG_COMPILE_CPP*/ - #if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ #pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ #endif /*_MSC_VER */ -const char* LODEPNG_VERSION_STRING = "20151024"; +const char* LODEPNG_VERSION_STRING = "20161127"; /* This source file is built up in the following large parts. The code sections @@ -251,17 +248,6 @@ p->data = NULL; p->size = p->allocsize = 0; } - -#ifdef LODEPNG_COMPILE_DECODER -/*resize and give all new elements the value*/ -static unsigned ucvector_resizev(ucvector* p, size_t size, unsigned char value) -{ - size_t oldsize = p->size, i; - if(!ucvector_resize(p, size)) return 0; - for(i = oldsize; i < size; ++i) p->data[i] = value; - return 1; -} -#endif /*LODEPNG_COMPILE_DECODER*/ #endif /*LODEPNG_COMPILE_PNG*/ #ifdef LODEPNG_COMPILE_ZLIB @@ -361,31 +347,53 @@ #ifdef LODEPNG_COMPILE_DISK -unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) +/* returns negative value on error. This should be pure C compatible, so no fstat. */ +static long lodepng_filesize(const char* filename) { FILE* file; long size; + file = fopen(filename, "rb"); + if(!file) return -1; - /*provide some proper output values if error will happen*/ - *out = 0; - *outsize = 0; + if(fseek(file, 0, SEEK_END) != 0) + { + fclose(file); + return -1; + } + + size = ftell(file); + /* It may give LONG_MAX as directory size, this is invalid for us. */ + if(size == LONG_MAX) size = -1; + fclose(file); + return size; +} + +/* load file into buffer that already has the correct allocated size. Returns error code.*/ +static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) +{ + FILE* file; + size_t readsize; file = fopen(filename, "rb"); if(!file) return 78; - /*get filesize:*/ - fseek(file , 0 , SEEK_END); - size = ftell(file); - rewind(file); + readsize = fread(out, 1, size, file); + fclose(file); + + if (readsize != size) return 78; + return 0; +} + +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) +{ + long size = lodepng_filesize(filename); + if (size < 0) return 78; + *outsize = (size_t)size; - /*read contents of the file into the vector*/ - *outsize = 0; *out = (unsigned char*)lodepng_malloc((size_t)size); - if(size && (*out)) (*outsize) = fread(*out, 1, (size_t)size, file); + if(!(*out) && size > 0) return 83; /*the above malloc failed*/ - fclose(file); - if(!(*out) && size) return 83; /*the above malloc failed*/ - return 0; + return lodepng_buffer_file(*out, (size_t)size, filename); } /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ @@ -719,14 +727,31 @@ return result; } -static int bpmnode_compare(const void* a, const void* b) +/*sort the leaves with stable mergesort*/ +static void bpmnode_sort(BPMNode* leaves, size_t num) { - int wa = ((const BPMNode*)a)->weight; - int wb = ((const BPMNode*)b)->weight; - if(wa < wb) return -1; - if(wa > wb) return 1; - /*make the qsort a stable sort*/ - return ((const BPMNode*)a)->index < ((const BPMNode*)b)->index ? 1 : -1; + BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); + size_t width, counter = 0; + for(width = 1; width < num; width *= 2) + { + BPMNode* a = (counter & 1) ? mem : leaves; + BPMNode* b = (counter & 1) ? leaves : mem; + size_t p; + for(p = 0; p < num; p += 2 * width) + { + size_t q = (p + width > num) ? num : (p + width); + size_t r = (p + 2 * width > num) ? num : (p + 2 * width); + size_t i = p, j = q, k; + for(k = p; k < r; k++) + { + if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; + else b[k] = a[j++]; + } + } + counter++; + } + if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num); + lodepng_free(mem); } /*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ @@ -806,7 +831,7 @@ BPMLists lists; BPMNode* node; - qsort(leaves, numpresent, sizeof(BPMNode), bpmnode_compare); + bpmnode_sort(leaves, numpresent); lists.listsize = maxbitlen; lists.memsize = 2 * maxbitlen * (maxbitlen + 1); @@ -1302,21 +1327,17 @@ given array must be sorted (if no value is smaller, it returns the size of the given array)*/ static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) { - /*linear search implementation*/ - /*for(size_t i = 1; i < array_size; ++i) if(array[i] > value) return i - 1; - return array_size - 1;*/ - - /*binary search implementation (not that much faster) (precondition: array_size > 0)*/ - size_t left = 1; + /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ + size_t left = 1; size_t right = array_size - 1; - while(left <= right) - { - size_t mid = (left + right) / 2; - if(array[mid] <= value) left = mid + 1; /*the value to find is more to the right*/ - else if(array[mid - 1] > value) right = mid - 1; /*the value to find is more to the left*/ - else return mid - 1; + + while(left <= right) { + size_t mid = (left + right) >> 1; + if (array[mid] >= value) right = mid - 1; + else left = mid + 1; } - return array_size - 1; + if(left >= array_size || array[left] > value) left--; + return left; } static void addLengthDistance(uivector* values, size_t length, size_t distance) @@ -1651,10 +1672,10 @@ if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; NLEN = 65535 - LEN; - ucvector_push_back(out, (unsigned char)(LEN % 256)); - ucvector_push_back(out, (unsigned char)(LEN / 256)); - ucvector_push_back(out, (unsigned char)(NLEN % 256)); - ucvector_push_back(out, (unsigned char)(NLEN / 256)); + ucvector_push_back(out, (unsigned char)(LEN & 255)); + ucvector_push_back(out, (unsigned char)(LEN >> 8)); + ucvector_push_back(out, (unsigned char)(NLEN & 255)); + ucvector_push_back(out, (unsigned char)(NLEN >> 8)); /*Decompressed data*/ for(j = 0; j < 65535 && datapos < datasize; ++j) @@ -1768,7 +1789,7 @@ else { if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); - for(i = datapos; i < dataend; ++i) lz77_encoded.data[i] = data[i]; /*no LZ77, but still will be Huffman compressed*/ + for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ } if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/); @@ -2186,8 +2207,8 @@ /*ucvector-controlled version of the output buffer, for dynamic array*/ ucvector_init_buffer(&outv, *out, *outsize); - ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256)); - ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256)); + ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8)); + ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255)); error = deflate(&deflatedata, &deflatesize, in, insize, settings); @@ -2335,17 +2356,18 @@ }; /*Return the CRC of the bytes buf[0..len-1].*/ -unsigned lodepng_crc32(const unsigned char* buf, size_t len) +unsigned lodepng_crc32(const unsigned char* data, size_t length) { - unsigned c = 0xffffffffL; - size_t n; - - for(n = 0; n < len; ++n) + unsigned r = 0xffffffffu; + size_t i; + for(i = 0; i < length; ++i) { - c = lodepng_crc32_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + r = lodepng_crc32_table[(r ^ data[i]) & 0xff] ^ (r >> 8); } - return c ^ 0xffffffffL; + return r ^ 0xffffffffu; } +#else /* !LODEPNG_NO_COMPILE_CRC */ +unsigned lodepng_crc32(const unsigned char* data, size_t length); #endif /* !LODEPNG_NO_COMPILE_CRC */ /* ////////////////////////////////////////////////////////////////////////// */ @@ -2363,9 +2385,10 @@ { unsigned result = 0; size_t i; - for(i = nbits - 1; i < nbits; --i) + for(i = 0 ; i < nbits; ++i) { - result += (unsigned)readBitFromReversedStream(bitpointer, bitstream) << i; + result <<= 1; + result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); } return result; } @@ -2684,12 +2707,18 @@ size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) { - return (w * h * lodepng_get_bpp(color) + 7) / 8; + /*will not overflow for any color type if roughly w * h < 268435455*/ + size_t bpp = lodepng_get_bpp(color); + size_t n = w * h; + return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8; } size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { - return (w * h * lodepng_get_bpp_lct(colortype, bitdepth) + 7) / 8; + /*will not overflow for any color type if roughly w * h < 268435455*/ + size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); + size_t n = w * h; + return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8; } @@ -2698,7 +2727,10 @@ /*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer*/ static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color) { - return h * ((w * lodepng_get_bpp(color) + 7) / 8); + /*will not overflow for any color type if roughly w * h < 268435455*/ + size_t bpp = lodepng_get_bpp(color); + size_t line = ((w / 8) * bpp) + ((w & 7) * bpp + 7) / 8; + return h * line; } #endif /*LODEPNG_COMPILE_DECODER*/ #endif /*LODEPNG_COMPILE_PNG*/ @@ -3401,25 +3433,26 @@ } else if(mode->colortype == LCT_RGB) { - *r = 256 * in[i * 6 + 0] + in[i * 6 + 1]; - *g = 256 * in[i * 6 + 2] + in[i * 6 + 3]; - *b = 256 * in[i * 6 + 4] + in[i * 6 + 5]; - if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; + *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; + *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; + if(mode->key_defined + && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; else *a = 65535; } else if(mode->colortype == LCT_GREY_ALPHA) { - *r = *g = *b = 256 * in[i * 4 + 0] + in[i * 4 + 1]; - *a = 256 * in[i * 4 + 2] + in[i * 4 + 3]; + *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; + *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; } else if(mode->colortype == LCT_RGBA) { - *r = 256 * in[i * 8 + 0] + in[i * 8 + 1]; - *g = 256 * in[i * 8 + 2] + in[i * 8 + 3]; - *b = 256 * in[i * 8 + 4] + in[i * 8 + 5]; - *a = 256 * in[i * 8 + 6] + in[i * 8 + 7]; + *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; + *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; + *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; + *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; } } @@ -3446,7 +3479,8 @@ /*if the user specified output palette but did not give the values, assume they want the values of the input color type (assuming that one is palette). Note that we never create a new palette ourselves.*/ - if(palettesize == 0) { + if(palettesize == 0) + { palettesize = mode_in->palettesize; palette = mode_in->palette; } @@ -3500,8 +3534,8 @@ { profile->colored = 0; profile->key = 0; - profile->alpha = 0; profile->key_r = profile->key_g = profile->key_b = 0; + profile->alpha = 0; profile->numcolors = 0; profile->bits = 1; } @@ -3588,8 +3622,8 @@ if(a != 65535 && (a != 0 || (profile->key && !matchkey))) { profile->alpha = 1; + profile->key = 0; alpha_done = 1; - if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ } else if(a == 0 && !profile->alpha && !profile->key) { @@ -3602,18 +3636,33 @@ { /* Color key cannot be used if an opaque pixel also has that RGB color. */ profile->alpha = 1; + profile->key = 0; alpha_done = 1; } } - if(alpha_done && numcolors_done && colored_done && bits_done) break; } + + if(profile->key && !profile->alpha) + { + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode); + if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + } + } + } } else /* < 16-bit */ { + unsigned char r = 0, g = 0, b = 0, a = 0; for(i = 0; i != numpixels; ++i) { - unsigned char r = 0, g = 0, b = 0, a = 0; getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode); if(!bits_done && profile->bits < 8) @@ -3637,6 +3686,7 @@ if(a != 255 && (a != 0 || (profile->key && !matchkey))) { profile->alpha = 1; + profile->key = 0; alpha_done = 1; if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ } @@ -3651,6 +3701,7 @@ { /* Color key cannot be used if an opaque pixel also has that RGB color. */ profile->alpha = 1; + profile->key = 0; alpha_done = 1; if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ } @@ -3678,6 +3729,22 @@ if(alpha_done && numcolors_done && colored_done && bits_done) break; } + if(profile->key && !profile->alpha) + { + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode); + if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + } + /*make the profile's key always 16-bit for consistency - repeat each byte twice*/ profile->key_r += (profile->key_r << 8); profile->key_g += (profile->key_g << 8); @@ -3699,7 +3766,7 @@ { LodePNGColorProfile prof; unsigned error = 0; - unsigned i, n, palettebits, grey_ok, palette_ok; + unsigned i, n, palettebits, palette_ok; lodepng_color_profile_init(&prof); error = lodepng_get_color_profile(&prof, image, w, h, mode_in); @@ -3709,14 +3776,14 @@ if(prof.key && w * h <= 16) { prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ + prof.key = 0; if(prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ } - grey_ok = !prof.colored && !prof.alpha; /*grey without alpha, with potentially low bits*/ n = prof.numcolors; palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); - palette_ok = n <= 256 && (n * 2 < w * h) && prof.bits <= 8; + palette_ok = n <= 256 && prof.bits <= 8; if(w * h < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ - if(grey_ok && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/ + if(!prof.colored && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/ if(palette_ok) { @@ -3745,7 +3812,7 @@ mode_out->colortype = prof.alpha ? (prof.colored ? LCT_RGBA : LCT_GREY_ALPHA) : (prof.colored ? LCT_RGB : LCT_GREY); - if(prof.key && !prof.alpha) + if(prof.key) { unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/ mode_out->key_r = prof.key_r & mask; @@ -3855,7 +3922,11 @@ { CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ } - if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') + if(lodepng_chunk_length(in + 8) != 13) + { + CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ + } + if(!lodepng_chunk_type_equals(in + 8, "IHDR")) { CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ } @@ -3930,13 +4001,13 @@ case 3: if(precon) { - for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + precon[i] / 2; - for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1); + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1); } else { for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth] / 2; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1); } break; case 4: @@ -4459,6 +4530,7 @@ ucvector scanlines; size_t predict; size_t numpixels; + size_t outsize = 0; /*for unknown chunk order*/ unsigned unknown = 0; @@ -4617,13 +4689,13 @@ /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/ const LodePNGColorMode* color = &state->info_png.color; predict = 0; - predict += lodepng_get_raw_size_idat((*w + 7) / 8, (*h + 7) / 8, color) + (*h + 7) / 8; - if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) / 8, (*h + 7) / 8, color) + (*h + 7) / 8; - predict += lodepng_get_raw_size_idat((*w + 3) / 4, (*h + 3) / 8, color) + (*h + 3) / 8; - if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) / 4, (*h + 3) / 4, color) + (*h + 3) / 4; - predict += lodepng_get_raw_size_idat((*w + 1) / 2, (*h + 1) / 4, color) + (*h + 1) / 4; - if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) / 2, (*h + 1) / 2, color) + (*h + 1) / 2; - predict += lodepng_get_raw_size_idat((*w + 0) / 1, (*h + 0) / 2, color) + (*h + 0) / 2; + predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3); + if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3); + predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color) + ((*h + 3) >> 3); + if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color) + ((*h + 3) >> 2); + predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color) + ((*h + 1) >> 2); + if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color) + ((*h + 1) >> 1); + predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color) + ((*h + 0) >> 1); } if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/ if(!state->error) @@ -4636,12 +4708,14 @@ if(!state->error) { - size_t outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); - ucvector outv; - ucvector_init(&outv); - if(!ucvector_resizev(&outv, outsize, 0)) state->error = 83; /*alloc fail*/ - if(!state->error) state->error = postProcessScanlines(outv.data, scanlines.data, *w, *h, &state->info_png); - *out = outv.data; + outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!*out) state->error = 83; /*alloc fail*/ + } + if(!state->error) + { + for(i = 0; i < outsize; i++) (*out)[i] = 0; + state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png); } ucvector_cleanup(&scanlines); } @@ -4718,7 +4792,7 @@ unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer; + unsigned char* buffer = 0; size_t buffersize; unsigned error; error = lodepng_load_file(&buffer, &buffersize, filename); @@ -4871,20 +4945,20 @@ { if(info->key_defined) { - ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255)); } } else if(info->colortype == LCT_RGB) { if(info->key_defined) { - ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_g / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_g % 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_b / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_b % 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_g >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_g & 255)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_b >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_b & 255)); } } @@ -5009,21 +5083,21 @@ ucvector_init(&bKGD); if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { - ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { - ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_g / 256)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_g % 256)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_b / 256)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_b % 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255)); } else if(info->color.colortype == LCT_PALETTE) { - ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); /*palette index*/ + ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/ } error = addChunk(out, "bKGD", bKGD.data, bKGD.size); @@ -5037,8 +5111,8 @@ unsigned error = 0; unsigned char* data = (unsigned char*)lodepng_malloc(7); if(!data) return 83; /*alloc fail*/ - data[0] = (unsigned char)(time->year / 256); - data[1] = (unsigned char)(time->year % 256); + data[0] = (unsigned char)(time->year >> 8); + data[1] = (unsigned char)(time->year & 255); data[2] = (unsigned char)time->month; data[3] = (unsigned char)time->day; data[4] = (unsigned char)time->hour; @@ -5093,13 +5167,13 @@ case 3: /*Average*/ if(prevline) { - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - prevline[i] / 2; - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) / 2); + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); } else { for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth] / 2; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); } break; case 4: /*Paeth*/ @@ -5184,14 +5258,14 @@ { /*adaptive filtering*/ size_t sum[5]; - ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ size_t smallest = 0; unsigned char type, bestType = 0; for(type = 0; type != 5; ++type) { - ucvector_init(&attempt[type]); - if(!ucvector_resize(&attempt[type], linebytes)) return 83; /*alloc fail*/ + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) return 83; /*alloc fail*/ } if(!error) @@ -5201,13 +5275,13 @@ /*try the 5 filter types*/ for(type = 0; type != 5; ++type) { - filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); /*calculate the sum of the result*/ sum[type] = 0; if(type == 0) { - for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type].data[x]); + for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type][x]); } else { @@ -5216,7 +5290,7 @@ /*For differences, each byte should be treated as signed, values above 127 are negative (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. This means filtertype 0 is almost never chosen, but that is justified.*/ - unsigned char s = attempt[type].data[x]; + unsigned char s = attempt[type][x]; sum[type] += s < 128 ? s : (255U - s); } } @@ -5233,24 +5307,24 @@ /*now fill the out values*/ out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; } } - for(type = 0; type != 5; ++type) ucvector_cleanup(&attempt[type]); + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); } else if(strategy == LFS_ENTROPY) { float sum[5]; - ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ float smallest = 0; unsigned type, bestType = 0; unsigned count[256]; for(type = 0; type != 5; ++type) { - ucvector_init(&attempt[type]); - if(!ucvector_resize(&attempt[type], linebytes)) return 83; /*alloc fail*/ + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) return 83; /*alloc fail*/ } for(y = 0; y != h; ++y) @@ -5258,9 +5332,9 @@ /*try the 5 filter types*/ for(type = 0; type != 5; ++type) { - filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); for(x = 0; x != 256; ++x) count[x] = 0; - for(x = 0; x != linebytes; ++x) ++count[attempt[type].data[x]]; + for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; ++count[type]; /*the filter type itself is part of the scanline*/ sum[type] = 0; for(x = 0; x != 256; ++x) @@ -5280,10 +5354,10 @@ /*now fill the out values*/ out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; } - for(type = 0; type != 5; ++type) ucvector_cleanup(&attempt[type]); + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); } else if(strategy == LFS_PREDEFINED) { @@ -5303,7 +5377,7 @@ deflate the scanline after every filter attempt to see which one deflates best. This is very slow and gives only slightly smaller, sometimes even larger, result*/ size_t size[5]; - ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ size_t smallest = 0; unsigned type = 0, bestType = 0; unsigned char* dummy; @@ -5319,20 +5393,20 @@ zlibsettings.custom_deflate = 0; for(type = 0; type != 5; ++type) { - ucvector_init(&attempt[type]); - ucvector_resize(&attempt[type], linebytes); /*todo: give error if resize failed*/ + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) return 83; /*alloc fail*/ } for(y = 0; y != h; ++y) /*try the 5 filter types*/ { for(type = 0; type != 5; ++type) { - unsigned testsize = attempt[type].size; + unsigned testsize = linebytes; /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ - filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); size[type] = 0; dummy = 0; - zlib_compress(&dummy, &size[type], attempt[type].data, testsize, &zlibsettings); + zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); lodepng_free(dummy); /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ if(type == 0 || size[type] < smallest) @@ -5343,9 +5417,9 @@ } prevline = &in[y * linebytes]; out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; } - for(type = 0; type != 5; ++type) ucvector_cleanup(&attempt[type]); + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); } else return 88; /* unknown filter strategy */ @@ -5610,7 +5684,7 @@ if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { unsigned char* converted; - size_t size = (w * h * lodepng_get_bpp(&info.color) + 7) / 8; + size_t size = (w * h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8; converted = (unsigned char*)lodepng_malloc(size); if(!converted && size) state->error = 83; /*alloc fail*/ @@ -5873,8 +5947,7 @@ case 43: return "bKGD chunk has wrong size for palette image"; case 44: return "bKGD chunk has wrong size for greyscale image"; case 45: return "bKGD chunk has wrong size for RGB image"; - /*the input data is empty, maybe a PNG file doesn't exist or is in the wrong path*/ - case 48: return "empty input or file doesn't exist"; + case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?"; case 49: return "jumped past memory while generating dynamic huffman tree"; case 50: return "jumped past memory while generating dynamic huffman tree"; case 51: return "jumped past memory while inflating huffman block"; @@ -5924,6 +5997,7 @@ case 91: return "invalid decompressed idat size"; case 92: return "too many pixels, not supported"; case 93: return "zero width or height is invalid"; + case 94: return "header chunk must have a size of 13 bytes"; } return "unknown error code"; } @@ -5940,27 +6014,18 @@ { #ifdef LODEPNG_COMPILE_DISK -void load_file(std::vector& buffer, const std::string& filename) +unsigned load_file(std::vector& buffer, const std::string& filename) { - std::ifstream file(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate); - - /*get filesize*/ - std::streamsize size = 0; - if(file.seekg(0, std::ios::end).good()) size = file.tellg(); - if(file.seekg(0, std::ios::beg).good()) size -= file.tellg(); - - /*read contents of the file into the vector*/ - buffer.resize(size_t(size)); - if(size > 0) file.read((char*)(&buffer[0]), size); + long size = lodepng_filesize(filename.c_str()); + if(size < 0) return 78; + buffer.resize((size_t)size); + return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str()); } /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ unsigned save_file(const std::vector& buffer, const std::string& filename) { - std::ofstream file(filename.c_str(), std::ios::out|std::ios::binary); - if(!file) return 79; - file.write(buffer.empty() ? 0 : (char*)&buffer[0], std::streamsize(buffer.size())); - return 0; + return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); } #endif /* LODEPNG_COMPILE_DISK */ @@ -6087,7 +6152,8 @@ LodePNGColorType colortype, unsigned bitdepth) { std::vector buffer; - load_file(buffer, filename); + unsigned error = load_file(buffer, filename); + if(error) return error; return decode(out, w, h, buffer, colortype, bitdepth); } #endif /* LODEPNG_COMPILE_DECODER */ diff -Nru refind-0.10.4/libeg/lodepng.h refind-0.11.2/libeg/lodepng.h --- refind-0.10.4/libeg/lodepng.h 2015-12-09 22:23:26.000000000 +0000 +++ refind-0.11.2/libeg/lodepng.h 2017-08-06 02:24:02.000000000 +0000 @@ -1,7 +1,7 @@ /* -LodePNG version 20151024 +LodePNG version 20161127 -Copyright (c) 2005-2015 Lode Vandevenne +Copyright (c) 2005-2016 Lode Vandevenne This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -51,11 +51,6 @@ #define memset(s, c, n) MyMemSet(s, c, n) #define memcpy(d, s, n) MyMemCpy(d, s, n) -#ifdef __cplusplus -#include -#include -#endif /*__cplusplus*/ - extern const char* LODEPNG_VERSION_STRING; /* @@ -109,6 +104,11 @@ #endif #endif +#ifdef LODEPNG_COMPILE_CPP +#include +#include +#endif /*LODEPNG_COMPILE_CPP*/ + #ifdef LODEPNG_COMPILE_PNG /*The PNG color types (also used for raw).*/ typedef enum LodePNGColorType @@ -582,11 +582,11 @@ typedef struct LodePNGColorProfile { unsigned colored; /*not greyscale*/ - unsigned key; /*if true, image is not opaque. Only if true and alpha is false, color key is possible.*/ - unsigned short key_r; /*these values are always in 16-bit bitdepth in the profile*/ + unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ + unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ unsigned short key_g; unsigned short key_b; - unsigned alpha; /*alpha channel or alpha palette required*/ + unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/ unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/ unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for greyscale only. 16 if 16-bit per channel required.*/ @@ -871,10 +871,10 @@ #ifdef LODEPNG_COMPILE_DISK /* -Load a file from disk into an std::vector. If the vector is empty, then either -the file doesn't exist or is an empty file. +Load a file from disk into an std::vector. +return value: error code (0 means ok) */ -void load_file(std::vector& buffer, const std::string& filename); +unsigned load_file(std::vector& buffer, const std::string& filename); /* Save the binary data in an std::vector to a file on disk. The file is overwritten @@ -919,8 +919,10 @@ [X] let the "isFullyOpaque" function check color keys and transparent palettes too [X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" [ ] don't stop decoding on errors like 69, 57, 58 (make warnings) +[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ... [ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes [ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... +[ ] allow user to give data (void*) to custom allocator */ #endif /*LODEPNG_H inclusion guard*/ @@ -950,8 +952,9 @@ 10. examples 10.1. decoder C++ example 10.2. decoder C example - 11. changes - 12. contact information + 11. state settings reference + 12. changes + 13. contact information 1. about @@ -1577,8 +1580,49 @@ return 0; } +11. state settings reference +---------------------------- + +A quick reference of some settings to set on the LodePNGState + +For decoding: + +state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums +state.decoder.zlibsettings.custom_...: use custom inflate function +state.decoder.ignore_crc: ignore CRC checksums +state.decoder.color_convert: convert internal PNG color to chosen one +state.decoder.read_text_chunks: whether to read in text metadata chunks +state.decoder.remember_unknown_chunks: whether to read in unknown chunks +state.info_raw.colortype: desired color type for decoded image +state.info_raw.bitdepth: desired bit depth for decoded image +state.info_raw....: more color settings, see struct LodePNGColorMode +state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo + +For encoding: + +state.encoder.zlibsettings.btype: disable compression by setting it to 0 +state.encoder.zlibsettings.use_lz77: use LZ77 in compression +state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize +state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match +state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching +state.encoder.zlibsettings.lazymatching: try one more LZ77 matching +state.encoder.zlibsettings.custom_...: use custom deflate function +state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png +state.encoder.filter_palette_zero: PNG filter strategy for palette +state.encoder.filter_strategy: PNG filter strategy to encode with +state.encoder.force_palette: add palette even if not encoding to one +state.encoder.add_id: add LodePNG identifier and version as a text chunk +state.encoder.text_compression: use compressed text chunks for metadata +state.info_raw.colortype: color type of raw input image you provide +state.info_raw.bitdepth: bit depth of raw input image you provide +state.info_raw: more color settings, see struct LodePNGColorMode +state.info_png.color.colortype: desired color type if auto_convert is false +state.info_png.color.bitdepth: desired bit depth if auto_convert is false +state.info_png.color....: more color settings, see struct LodePNGColorMode +state.info_png....: more PNG related settings, see struct LodePNGInfo + -11. changes +12. changes ----------- The version number of LodePNG is the date of the change given in the format @@ -1587,6 +1631,11 @@ Some changes aren't backwards compatible. Those are indicated with a (!) symbol. +*) 27 nov 2016: grey+alpha auto color model detection bugfix +*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). +*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within + the limits of pure C90). +*) 08 dec 2015: Made load_file function return error if file can't be opened. *) 24 okt 2015: Bugfix with decoding to palette output. *) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. *) 23 aug 2014: Reduced needless memory usage of decoder. @@ -1719,7 +1768,7 @@ *) 12 aug 2005: Initial release (C++, decoder only) -12. contact information +13. contact information ----------------------- Feel free to contact me with suggestions, problems, comments, ... concerning @@ -1731,5 +1780,5 @@ Account: lode dot vandevenne. -Copyright (c) 2005-2015 Lode Vandevenne +Copyright (c) 2005-2016 Lode Vandevenne */ diff -Nru refind-0.10.4/libeg/screen.c refind-0.11.2/libeg/screen.c --- refind-0.10.4/libeg/screen.c 2016-01-30 18:45:12.000000000 +0000 +++ refind-0.11.2/libeg/screen.c 2017-08-04 13:13:20.000000000 +0000 @@ -177,7 +177,7 @@ EFI_STATUS Status = EFI_SUCCESS; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; UINTN Size; - UINT32 ModeNum = 0; + UINT32 ModeNum = 0, CurrentModeNum; UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate; BOOLEAN ModeSet = FALSE; @@ -185,9 +185,12 @@ return FALSE; if (GraphicsOutput != NULL) { // GOP mode (UEFI) + CurrentModeNum = GraphicsOutput->Mode->Mode; if (*ScreenHeight == 0) { // User specified a mode number (stored in *ScreenWidth); use it directly ModeNum = (UINT32) *ScreenWidth; - if (egGetResFromMode(ScreenWidth, ScreenHeight) && + if (ModeNum != CurrentModeNum) { + ModeSet = TRUE; + } else if (egGetResFromMode(ScreenWidth, ScreenHeight) && (refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum) == EFI_SUCCESS)) { ModeSet = TRUE; } @@ -199,9 +202,10 @@ do { Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info); if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info) && (Info != NULL)) && - (Info->HorizontalResolution == *ScreenWidth) && (Info->VerticalResolution == *ScreenHeight)) { - Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum); - ModeSet = (Status == EFI_SUCCESS); + (Info->HorizontalResolution == *ScreenWidth) && (Info->VerticalResolution == *ScreenHeight) && + ((ModeNum == CurrentModeNum) || + (refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum) == EFI_SUCCESS))) { + ModeSet = TRUE; } // if } while ((++ModeNum < GraphicsOutput->Mode->MaxMode) && !ModeSet); } // if/else @@ -217,6 +221,10 @@ Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info); if ((Status == EFI_SUCCESS) && (Info != NULL)) { Print(L"Mode %d: %d x %d\n", ModeNum, Info->HorizontalResolution, Info->VerticalResolution); + if (ModeNum == CurrentModeNum) { + egScreenWidth = Info->HorizontalResolution; + egScreenHeight = Info->VerticalResolution; + } // if } // else } while (++ModeNum < GraphicsOutput->Mode->MaxMode); PauseForKey(); @@ -441,8 +449,9 @@ // Display a message in the center of the screen, surrounded by a box of the // specified color. For the moment, uses graphics calls only. (It still works // in text mode on GOP/UEFI systems, but not on UGA/EFI 1.x systems.) -VOID egDisplayMessage(IN CHAR16 *Text, EG_PIXEL *BGColor) { +VOID egDisplayMessage(IN CHAR16 *Text, EG_PIXEL *BGColor, UINTN PositionCode) { UINTN BoxWidth, BoxHeight; + static UINTN Position = 1; EG_IMAGE *Box; if ((Text != NULL) && (BGColor != NULL)) { @@ -453,20 +462,42 @@ BoxWidth = egScreenWidth; Box = egCreateFilledImage(BoxWidth, BoxHeight, FALSE, BGColor); egRenderText(Text, Box, 7, BoxHeight / 4, (BGColor->r + BGColor->g + BGColor->b) / 3); - egDrawImage(Box, (egScreenWidth - BoxWidth) / 2, (egScreenHeight - BoxHeight) / 2); + switch (PositionCode) { + case CENTER: + Position = (egScreenHeight - BoxHeight) / 2; + break; + case BOTTOM: + Position = egScreenHeight - (BoxHeight * 2); + break; + case TOP: + Position = 1; + break; + default: // NEXTLINE + Position += BoxHeight + (BoxHeight / 10); + break; + } // switch() + egDrawImage(Box, (egScreenWidth - BoxWidth) / 2, Position); + if ((PositionCode == CENTER) || (Position >= egScreenHeight - (BoxHeight * 5))) + Position = 1; } // if non-NULL inputs } // VOID egDisplayMessage() // Copy the current contents of the display into an EG_IMAGE.... // Returns pointer if successful, NULL if not. EG_IMAGE * egCopyScreen(VOID) { + return egCopyScreenArea(0, 0, egScreenWidth, egScreenHeight); +} // EG_IMAGE * egCopyScreen() + +// Copy the current contents of the specified display area into an EG_IMAGE.... +// Returns pointer if successful, NULL if not. +EG_IMAGE * egCopyScreenArea(UINTN XPos, UINTN YPos, UINTN Width, UINTN Height) { EG_IMAGE *Image = NULL; if (!egHasGraphics) return NULL; - // allocate a buffer for the whole screen - Image = egCreateImage(egScreenWidth, egScreenHeight, FALSE); + // allocate a buffer for the screen area + Image = egCreateImage(Width, Height, FALSE); if (Image == NULL) { return NULL; } @@ -474,13 +505,13 @@ // get full screen image if (GraphicsOutput != NULL) { refit_call10_wrapper(GraphicsOutput->Blt, GraphicsOutput, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)Image->PixelData, - EfiBltVideoToBltBuffer, 0, 0, 0, 0, Image->Width, Image->Height, 0); + EfiBltVideoToBltBuffer, XPos, YPos, 0, 0, Image->Width, Image->Height, 0); } else if (UgaDraw != NULL) { refit_call10_wrapper(UgaDraw->Blt, UgaDraw, (EFI_UGA_PIXEL *)Image->PixelData, EfiUgaVideoToBltBuffer, - 0, 0, 0, 0, Image->Width, Image->Height, 0); + XPos, YPos, 0, 0, Image->Width, Image->Height, 0); } return Image; -} // EG_IMAGE * egCopyScreen() +} // EG_IMAGE * egCopyScreenArea() // // Make a screenshot diff -Nru refind-0.10.4/libeg/text.c refind-0.11.2/libeg/text.c --- refind-0.10.4/libeg/text.c 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/libeg/text.c 2017-07-30 13:21:02.000000000 +0000 @@ -38,6 +38,7 @@ #include "../refind/global.h" #include "egemb_font.h" +#include "egemb_font_large.h" #define FONT_NUM_CHARS 96 static EG_IMAGE *BaseFontImage = NULL; @@ -51,11 +52,17 @@ // static VOID egPrepareFont() { - if (BaseFontImage == NULL) { - BaseFontImage = egPrepareEmbeddedImage(&egemb_font, TRUE); - } - if (BaseFontImage != NULL) - FontCellWidth = BaseFontImage->Width / FONT_NUM_CHARS; + UINTN UGAWidth, UGAHeight; + + egGetScreenSize(&UGAWidth, &UGAHeight); + if (BaseFontImage == NULL) { + if (UGAWidth >= HIDPI_MIN) + BaseFontImage = egPrepareEmbeddedImage(&egemb_font_large, TRUE); + else + BaseFontImage = egPrepareEmbeddedImage(&egemb_font, TRUE); + } + if (BaseFontImage != NULL) + FontCellWidth = BaseFontImage->Width / FONT_NUM_CHARS; } // VOID egPrepareFont(); UINTN egGetFontHeight(VOID) { @@ -76,8 +83,7 @@ return Width; } // UINTN egComputeTextWidth() -VOID egMeasureText(IN CHAR16 *Text, OUT UINTN *Width, OUT UINTN *Height) -{ +VOID egMeasureText(IN CHAR16 *Text, OUT UINTN *Width, OUT UINTN *Height) { egPrepareFont(); if (Width != NULL) diff -Nru refind-0.10.4/Make.common refind-0.11.2/Make.common --- refind-0.10.4/Make.common 2015-12-10 16:58:16.000000000 +0000 +++ refind-0.11.2/Make.common 2017-07-30 19:24:25.000000000 +0000 @@ -31,9 +31,8 @@ HOSTARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) ARCH ?= $(HOSTARCH) -# Note: EDK2BASE is definted in master Makefile and exported -#EDK2BASE = /usr/local/UDK2014/MyWorkSpace -GENFW = $(EDK2BASE)/BaseTools/Source/C/bin/GenFw +# Note: TIANOBASE is defined in master Makefile and exported +GENFW = $(TIANOBASE)/BaseTools/Source/C/bin/GenFw prefix = /usr/bin/ ifeq ($(ARCH),aarch64) CC = $(prefix)aarch64-linux-gnu-gcc @@ -53,7 +52,7 @@ ifeq ($(MAKEWITH),TIANO) # Below file defines TARGET (RELEASE or DEBUG) and TOOL_CHAIN_TAG (GCC44, GCC45, GCC46, or GCC47) -include $(EDK2BASE)/Conf/target.txt +include $(TIANOBASE)/Conf/target.txt endif # @@ -68,12 +67,12 @@ GNUEFI_CFLAGS = -fpic -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol -I../include -I../refind -I../libeg -I../mok # ...and for TianoCore.... -TIANO_INCLUDE_DIRS = -I $(EDK2BASE)/MdePkg \ - -I $(EDK2BASE)/MdePkg/Include \ - -I $(EDK2BASE)/MdeModulePkg/ \ - -I $(EDK2BASE)/MdeModulePkg/Include \ - -I $(EDK2BASE)/IntelFrameworkPkg/Include \ - -I $(EDK2BASE)/MdePkg/Include/$(ARCHDIR) \ +TIANO_INCLUDE_DIRS = -I $(TIANOBASE)/MdePkg \ + -I $(TIANOBASE)/MdePkg/Include \ + -I $(TIANOBASE)/MdeModulePkg/ \ + -I $(TIANOBASE)/MdeModulePkg/Include \ + -I $(TIANOBASE)/IntelFrameworkPkg/Include \ + -I $(TIANOBASE)/MdePkg/Include/$(ARCHDIR) \ -I .. \ -I ../refind \ -I ../libeg \ @@ -93,8 +92,9 @@ # ...and for TianoCore.... ENTRYPOINT=efi_main -TIANO_LDSCRIPT = $(EDK2BASE)/BaseTools/Scripts/gcc4.4-ld-script -TIANO_LDFLAGS = -nostdlib -n -q --gc-sections --script=$(EDK2BASE)/BaseTools/Scripts/gcc4.4-ld-script \ +TIANO_LDSCRIPT = $(TIANOBASE)/BaseTools/Scripts/gcc4.9-ld-script +#TIANO_LDSCRIPT = /usr/local/UDK2014/MyWorkSpace/BaseTools/Scripts/gcc4.9-ld-script +TIANO_LDFLAGS = -nostdlib -n -q --gc-sections --script=$(TIANO_LDSCRIPT) \ --entry $(ENTRYPOINT) -u $(ENTRYPOINT) -m $(LD_CODE) # @@ -162,12 +162,12 @@ # GNU-EFI compilation path uses .o files for compiled object code %.o: %.c $(CC) $(CFLAGS) $(ARCH_CFLAGS) $(GNUEFI_CFLAGS) $(LOCAL_GNUEFI_CFLAGS) \ - -D__MAKEWITH_GNUEFI -DREFIND_VERSION=$(REFIND_VERSION) -c $< -o $@ + -D__MAKEWITH_GNUEFI -c $< -o $@ # TianoCore compilation path uses .obj files for compiled object code %.obj: %.c $(CC) $(CFLAGS) $(ARCH_CFLAGS) $(TIANO_INCLUDE_DIRS) -DNO_BUILTIN_VA_FUNCS \ - -D__MAKEWITH_TIANO -DREFIND_VERSION=$(REFIND_VERSION) -c $< -o $@ + -D__MAKEWITH_TIANO -c $< -o $@ # rules for EFI applications diff -Nru refind-0.10.4/Makefile refind-0.11.2/Makefile --- refind-0.10.4/Makefile 2016-10-09 16:52:31.000000000 +0000 +++ refind-0.11.2/Makefile 2017-07-30 20:31:39.000000000 +0000 @@ -5,24 +5,43 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +include Make.common + +SHELL=/bin/bash LOADER_DIR=refind FS_DIR=filesystems LIBEG_DIR=libeg MOK_DIR=mok GPTSYNC_DIR=gptsync EFILIB_DIR=EfiLib -export EDK2BASE=/usr/local/UDK2014/MyWorkSpace -export REFIND_VERSION='L"0.10.4"' +# Two possible locations for TianoCore toolkit: +# TIANOBASE is used with "tiano" targets and +# EDK2BASE is used with "edk2" targets +export TIANOBASE=/usr/local/UDK2014/MyWorkSpace +export EDK2BASE=/usr/local/edk2-vUDK2017 +# NOTE: Below is overridden for "tiano" targets +-include $(EDK2BASE)/Conf/target.txt +THISDIR=$(shell pwd) +EDK2_BUILDLOC=$(EDK2BASE)/Build/Refind/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH) +EDK2_PROGRAM_BASENAMES=refind gptsync +EDK2_PROGRAMS=$(EDK2_PROGRAM_BASENAMES:=.efi) +EDK2_DRIVER_BASENAMES=btrfs ext4 ext2 hfs iso9660 ntfs reiserfs +EDK2_DRIVERS=$(EDK2_DRIVER_BASENAMES:=.efi) +EDK2_ALL_BASENAMES=$(EDK2_PROGRAM_BASENAMES) $(EDK2_DRIVER_BASENAMES) +EDK2_ALL_FILES=$(EDK2_ALL_BASENAMES:=.efi) # The "all" target builds with the TianoCore library if possible, but falls # back on the more easily-installed GNU-EFI library if TianoCore isn't -# installed at $(EDK2BASE) +# installed at $(EDK2BASE) or $(TIANOBASE) all: ifneq ($(wildcard $(EDK2BASE)/*),) - @echo "Found $(EDK2BASE); building with TianoCore" + @echo "Found $(EDK2BASE); building with TianoCore EDK2" + +make edk2 +else ifneq ($(wildcard $(TIANOBASE)/*),) + @echo "Found $(TIANOBASE); building with TianoCore UDK2014" +make tiano else - @echo "Did not find $(EDK2BASE); building with GNU-EFI" + @echo "Did not find $(EDK2BASE) or $(TIANOBASE); building with GNU-EFI" +make gnuefi endif @@ -30,35 +49,36 @@ # back to GNU-EFI. fs: ifneq ($(wildcard $(EDK2BASE)/*),) - @echo "Found $(EDK2BASE); building with TianoCore" + @echo "Found $(EDK2BASE); building with TianoCore EDK2" + +make fs_edk2 +else ifneq ($(wildcard $(TIANOBASE)/*),) + @echo "Found $(TIANOBASE); building with TianoCore UDK2014" +make fs_tiano else - @echo "Did not find $(EDK2BASE); building with GNU-EFI" + @echo "Did not find $(EDK2BASE) or $(TIANOBASE); building with GNU-EFI" +make fs_gnuefi endif # Likewise for GPTsync.... -GPTsync: +gptsync: ifneq ($(wildcard $(EDK2BASE)/*),) - @echo "Found $(EDK2BASE); building with TianoCore" + @echo "Found $(EDK2BASE); building with TianoCore EDK2" + +make gptsync_edk2 +else ifneq ($(wildcard $(TIANOBASE)/*),) + @echo "Found $(TIANOBASE); building with TianoCore UDK2014" +make gptsync_tiano else - @echo "Did not find $(EDK2BASE); building with GNU-EFI" + @echo "Did not find $(EDK2BASE) or $(TIANOBASE); building with GNU-EFI" +make gptsync_gnuefi endif -# Don't build gptsync under TianoCore by default because it errors out when -# using a cross-compiler on an x86-64 system. Because gptsync is pretty -# useless on ARM64, skipping it is no big deal.... -tiano: - +make MAKEWITH=TIANO AR_TARGET=EfiLib -C $(EFILIB_DIR) -f Make.tiano - +make MAKEWITH=TIANO AR_TARGET=libeg -C $(LIBEG_DIR) -f Make.tiano - +make MAKEWITH=TIANO AR_TARGET=mok -C $(MOK_DIR) -f Make.tiano - +make MAKEWITH=TIANO BUILDME=refind DLL_TARGET=refind -C $(LOADER_DIR) -f Make.tiano -ifneq ($(ARCH),aarch64) - +make MAKEWITH=TIANO -C $(GPTSYNC_DIR) -f Make.tiano -endif -# +make MAKEWITH=TIANO -C $(FS_DIR) +########################################################################### +# +# GNU-EFI build rules; should work with any CPU architecture and GNU-EFI +# version 3.0u or later, but cross-compiling requires adding odd +# components and is untested.... +# +########################################################################### gnuefi: +make MAKEWITH=GNUEFI -C $(LIBEG_DIR) @@ -66,20 +86,97 @@ +make MAKEWITH=GNUEFI -C $(EFILIB_DIR) +make MAKEWITH=GNUEFI -C $(LOADER_DIR) +make MAKEWITH=GNUEFI -C $(GPTSYNC_DIR) gnuefi -# +make MAKEWITH=GNUEFI -C $(FS_DIR) all_gnuefi -fs_tiano: - +make MAKEWITH=TIANO -C $(FS_DIR) +all_gnuefi: gnuefi fs_gnuefi + +gptsync_gnuefi: + +make MAKEWITH=GNUEFI -C $(GPTSYNC_DIR) gnuefi fs_gnuefi: +make MAKEWITH=GNUEFI -C $(FS_DIR) all_gnuefi +########################################################################### +# +# Old-style TianoCore build rules; useful only with UDK2014 development +# kit.... +# +########################################################################### + +# Don't build gptsync under TianoCore/AARCH64 by default because it errors out +# when using a cross-compiler on an x86-64 system. Because gptsync is pretty +# useless on ARM64, skipping it is no big deal.... +tiano: + -include $(TIANOBASE)/Conf/target.txt + +make MAKEWITH=TIANO AR_TARGET=EfiLib -C $(EFILIB_DIR) -f Make.tiano + +make MAKEWITH=TIANO AR_TARGET=libeg -C $(LIBEG_DIR) -f Make.tiano + +make MAKEWITH=TIANO AR_TARGET=mok -C $(MOK_DIR) -f Make.tiano + +make MAKEWITH=TIANO BUILDME=refind DLL_TARGET=refind -C $(LOADER_DIR) -f Make.tiano +ifneq ($(ARCH),aarch64) + +make MAKEWITH=TIANO -C $(GPTSYNC_DIR) -f Make.tiano +endif +# +make MAKEWITH=TIANO -C $(FS_DIR) + +all_tiano: tiano fs_tiano + gptsync_tiano: + -include $(TIANOBASE)/Conf/target.txt +make MAKEWITH=TIANO -C $(GPTSYNC_DIR) -f Make.tiano -gptsync_gnuefi: - +make MAKEWITH=GNUEFI -C $(GPTSYNC_DIR) gnuefi +fs_tiano: + -include $(TIANOBASE)/Conf/target.txt + +make MAKEWITH=TIANO -C $(FS_DIR) + +########################################################################### +# +# New-style build rules for use with TianoCore via its own "build" tool. +# Works with UDK2014 and late-March EDK2; but UDK2014 builds fail with +# AARCH64 unless .inf files are modified to eliminate references to +# CompilerIntrinsicsLib.... +# +# NOTE: Unlike other build rules, these build everything (rEFInd, gptsync, +# and filesystem drivers), even if only one component is requested; but +# only the requested components are copied to their final destinations. +# This is done because of the heavy overhead in building just one +# component in the TianoCore "build" tool. +# +########################################################################### + +# Build process for TianoCore using TianoCore-standard build process rather +# than my own custom Makefiles (except this top-level one) +edk2: build_edk2 + cp $(EDK2_BUILDLOC)/refind.efi ./refind/refind_$(FILENAME_CODE).efi + cp $(EDK2_BUILDLOC)/gptsync.efi ./gptsync/gptsync_$(FILENAME_CODE).efi + +all_edk2: build_edk2 fs_edk2 + cp $(EDK2_BUILDLOC)/refind.efi ./refind/refind_$(FILENAME_CODE).efi + cp $(EDK2_BUILDLOC)/gptsync.efi ./gptsync/gptsync_$(FILENAME_CODE).efi + +gptsync_edk2: build_edk2 + cp $(EDK2_BUILDLOC)/gptsync.efi ./gptsync/gptsync_$(FILENAME_CODE).efi + +fs_edk2: build_edk2 + for BASENAME in $(EDK2_DRIVER_BASENAMES) ; do \ + echo "Copying $$BASENAME""_$(FILENAME_CODE).efi" ; \ + cp "$(EDK2_BUILDLOC)/$$BASENAME.efi" ./drivers_$(FILENAME_CODE)/$$BASENAME\_$(FILENAME_CODE).efi ; \ + done + +build_edk2: $(EDK2BASE)/RefindPkg + cd $(EDK2BASE) && \ + . ./edksetup.sh BaseTools && \ + build -a $(UC_ARCH) -p RefindPkg/RefindPkg.dsc + mkdir -p ./drivers_$(FILENAME_CODE) + +$(EDK2BASE)/RefindPkg: + ln -s $(THISDIR) $(EDK2BASE)/RefindPkg + +########################################################################### +# +# Build rules that are not dependent on the toolkit.... +# +########################################################################### +# NOTE: This "clean" rule cleans intermediate components for all three +# build styles (tiano, edk2, and gnuefi). clean: make -C $(LIBEG_DIR) clean make -C $(MOK_DIR) clean @@ -88,6 +185,9 @@ make -C $(FS_DIR) clean make -C $(GPTSYNC_DIR) clean rm -f include/*~ + rm -rf $(EDK2BASE)/Build/Refind + rm -rf drivers_$(FILENAME_CODE)/* + [ ! -L $(EDK2BASE)/RefindPkg ] || rm -v $(EDK2BASE)/RefindPkg # NOTE TO DISTRIBUTION MAINTAINERS: # The "install" target installs the program directly to the ESP diff -Nru refind-0.10.4/mvrefind refind-0.11.2/mvrefind --- refind-0.10.4/mvrefind 2016-01-26 19:44:54.000000000 +0000 +++ refind-0.11.2/mvrefind 2017-08-03 01:56:41.000000000 +0000 @@ -20,6 +20,7 @@ # # Revision history: # +# 0.11.0 -- Added creation of BOOT.CSV file to tasks # 0.10.2 -- Fixed bug in moving bootmgfw.efi in some situations # 0.10.1 -- Generalized to support ARM64 (aka AARCH64, aa64) # 0.10.0 -- Renamed from mvrefind.sh to mvrefind @@ -31,8 +32,8 @@ RootDir="/" SourceShim="shim.efi" TargetShim=$SourceShim -SourceDir=`readlink -f ${1}` -TargetDir=`readlink -f ${2}` +SourceDir=`readlink -m ${1}` +TargetDir=`readlink -m ${2}` # Identifies the ESP's location (/boot or /boot/efi); aborts if the ESP isn't # mounted at either location. Also splits the ESP location from SourceDir and @@ -201,19 +202,31 @@ mv $SourceDir/$Source $TargetDir/$Target 2> /dev/null mv $SourceDir/$SourceShim $TargetDir/$TargetShim 2> /dev/null mv $SourceDir/refind.conf* $TargetDir/ 2> /dev/null + rm $SourceDir/BOOT.CSV rmdir $SourceDir 2> /dev/null } # MoveFiles() # Clean up after moving files -- mainly restoring old backed-up files, if present PostMoveCleanup() { - if [[ $EfiSourceDir == "/efi/boot" && -d $InstallDir/EFI/BOOT-rEFIndBackup && ! -d $SourceDir ]] ; then - mv $InstallDir/EFI/BOOT-rEFIndBackup $SourceDir 2> /dev/null + if [[ "$EspSourceDir" == "/efi/boot" && -d "$InstallDir/EFI/BOOT-rEFIndBackup" && ! -d $SourceDir ]] ; then + mv "$InstallDir/EFI/BOOT-rEFIndBackup" "$SourceDir" 2> /dev/null fi - if [[ $EfiSourceDir == "/efi/microsoft/boot" && -f $InstallDir/EFI/Microsoft/bootmgfw.efi ]] ; then - mv -n $InstallDir/EFI/Microsoft/bootmgfw.efi $SourceDir/bootmgfw.efi + if [[ "$EspSourceDir" == "/efi/microsoft/boot" && -f "$InstallDir/EFI/Microsoft/bootmgfw.efi" ]] ; then + mv -n "$InstallDir/EFI/Microsoft/bootmgfw.efi" "$SourceDir/bootmgfw.efi" fi } # PostMoveCleanup() +# Create a BOOT.CSV file in the same directory as rEFInd, to help in recovery +# should the system's boot entry list be lost +CreateBootCsvFile() { + IConv=`which iconv 2> /dev/null` + if [[ -x "$IConv" && -d "$TargetDir" ]] ; then + echo "$Target,rEFInd boot manager,,This is the boot entry for rEFInd" | \ + $IConv -t UCS-2 > "$TargetDir/BOOT.CSV" + fi + exit +} # CreateBootCsvFile() + # If necessary, create a new NVRAM entry for the new location AddNvramEntry() { InstallIt="0" @@ -281,4 +294,5 @@ CheckForFiles MoveFiles PostMoveCleanup +CreateBootCsvFile AddNvramEntry diff -Nru refind-0.10.4/NEWS.txt refind-0.11.2/NEWS.txt --- refind-0.10.4/NEWS.txt 2016-10-09 23:09:03.000000000 +0000 +++ refind-0.11.2/NEWS.txt 2017-10-22 20:03:19.000000000 +0000 @@ -1,3 +1,225 @@ +0.11.2 (10/22/2017): +-------------------- + +- Fixed a bug that caused the hidden-tags feature to not work unless + it was explicitly set in refind.conf. (It should have been enabled by + default, and now it is.) + +- Fixed a bug (introduced in 0.11.1) that caused setting volumes in + manual boot stanzas to fail. + +0.11.1 (10/9/2017): +------------------- + +- Modified refind-install to be smarter about modifying NVRAM entries under + Linux. It now re-creates existing rEFInd entries only if the existing + entries don't point to the same location that rEFInd will use. + +- Modified the way rEFInd tracks boot loader files. This was made necessary + by macOS 10.13/APFS, which was confusing rEFInd's old tracking code when + it was compiled with GNU-EFI. Ideally, this will have no noticeable effect + to end users; however, it's possible that some loaders will appear or + disappear from the menu, or "file not found" errors when launching loaders + will go away, after upgrading to this version of rEFInd. + +- Added support for new macOS boot loader locations used in macOS 10.13 + ("High Sierra"). + +- Fixed bug that could cause hidden-tag maintenance tool to hang. + +- Fixed bug, introduced in 0.11.0, that caused the Apple and Microsoft + recovery tools to not be detected. + +0.11.0 (8/13/2017): +------------------- + +- Fixed lack of scaling of disk badges when other icons were properly scaled + on HiDPI/retina displays. + +- Added new --encryptkeys option to refind-install, to improve the security + of locally-generated Secure Boot keys stored on your computer's hard disk. + +- Fixed spoof_osx_version to work with newer Apple EFIs. + +- Added new mouse support: Uncomment enable_mouse in refind.conf to activate + this support. You can select an OS to launch with this feature active, but + you cannot use submenus via the mouse. The mouse_size and mouse_speed + tokens control the mouse size in pixels and tracking speed, respectively. + Note that not all computers support mice in their EFIs, which is why this + feature is disabled by default. + +- Fixed bug that caused specifying a full path to the fallback boot + loader (EFI/BOOT/bootx64.efi) in dont_scan_files to fail to work. + +- Added dont_scan_tools refind.conf token to enable hiding EFI tools. + This feature overrides scantools -- if the latter includes, say, "shell", + but the former includes "shell.efi", any shell called "shell.efi" will be + ignored. As with dont_scan_files, you can specify a "bare" filename or a + complete path. The point is to enable hiding redundant tools -- say, if + multiple MokManager tools show up in the menu and you want just one. + +- A new feature enables you to hide OSes and external tool tags from the + rEFInd main menu: Highlight the OS tag and hit "-" or the Delete key. The + OS tag should disappear, and remain gone between reboots. A new tool tag + (on the second row) with a recycling icon enables recovering OS tags + hidden in this way. + +- You can now specify volumes by GUID number in dont_scan_dirs and + dont_scan_files specifications -- e.g., "dont_scan_files + 2C17D5ED-850D-4F76-BA31-47A561740082:\EFI\badloader\badloader.efi" to keep + EFI\badloader\badloader.efi on the volume with a partition GUID value of + 2C17D5ED-850D-4F76-BA31-47A561740082 off the menu. + +- I've removed support for the previously-deprecated volume-number style + volume specifications (fs0:, fs1:, etc.). + +- Fixed bug in mvrefind that caused it to not move the EFI/BOOT-rEFIndBackup + directory back to EFI/BOOT when renaming rEFInd in EFI/BOOT to something + else. + +- The refind-install and mvrefind scripts now create a BOOT.CSV file in the + rEFInd installation directory. The fallback.efi (aka fbx64.efi) program + delivered with many distributions can use this file to re-create rEFInd's + NVRAM boot entry should it be lost. Some distributions (such as Fedora) + set up fallback.efi in the EFI/BOOT directory on the ESP, so it will run + automatically if NVRAM variables are lost. All this said, there's no + guarantee that rEFInd will be FIRST in the boot order should the NVRAM + entries be lost. + +- Improved error messaging on Macs; most serious system errors should now + be reported on-screen in graphics mode. + +- Fixed bug that caused Fedora/CentOS/RHEL "vmlinuz-0-rescue*" kernels to + not be sorted down in the kernel list if they happened to be the first + ones passed to rEFInd by the EFI. + +0.10.9 (7/30/2017): +------------------- + +- The PauseForKey() function now works on Macs in graphics mode, which can + help when some errors are encountered. (Most of the errors associated with + this function still rely on Print(), which still doesn't work on Macs; but + at least there will be a prompt to press a key.) + +- rEFInd now displays its background and banner before scanning for boot + loaders, and displays a message that it's performing this scan. + +- Added support for HiDPI/retina displays: rEFInd now automatically scales + icons and text to twice the normal size when the screen's horizontal + resolution is above 1920. This does not occur in text mode (you must still + select an appropriate text-mode resolution via the "textmode" option in + refind.conf), and it can be overridden by explicitly setting the + "small_icon_size", "big_icon_size", and "font" options in refind.conf. + Note that icons are resized from their originals and so may look a bit + chunky, by HiDPI standards; but rEFInd now embeds both 14- and 28-point + fonts, so the fonts will look better. If the screen is HiDPI but 1920 + pixels wide or less, the default icon and font sizes are used, so + adjustment via refind.conf options may still be desirable. + +- Added os_trusty.png, os_xenial.png and os_zesty.png icons, for those who + have multiple Ubuntu versions and want to distinguish them visually. + +- Updated LodePNG, which is used to load PNG images, to the latest version + (20161127). + +- A new "edk2" target to "make" is available, which builds in the standard + TianoCore way. This has the advantage over the "tiano" target of working + with newer versions of EDK2, including the recently-released UDK2017 + . (The + "tiano" target maxes out at UDK2014.) + +- Improved compatibility with standard TianoCore-style build process; can + now build rEFInd binary, gptsync, and drivers in the "TianoCore" way, in + addition to by using Linux Makefiles. + +0.10.8 (5/21/2017): +------------------- + +- Added shimx64.efi.signed as a valid Shim source filename, and + mm{arch}.efi.signed as a valid MokManager source filename, to + refind-install script. This enables users on Ubuntu to point to Ubuntu's + signed Shim and MokManager files, which are stored in /usr/lib/shim under + these odd filenames. + +- Fixed compile problems with GNU-EFI 3.0.5. + +- Added icon for Devuan GNU+Linux, based on the icon in the Devuan press kit + (https://devuan.org/os/press/). + +- Minor code efficiency improvements. + +- Added ability to specify volumes by partition unique GUIDs in + dont_scan_volumes. + +- Renamed "Mac OS X" to "macOS" in assorted messages, per Apple's + re-branding with version 10.12 (Sierra). Unfortunately, I don't know of an + easy way to tell which macOS version a given macOS boot loader will load, + so it's one name or the other for everything. + +0.10.7 (4/17/2017): +------------------- + +- Update refind-install to recognize and copy mmx64.efi as alternative + name for MokManager. + +- Hide volume name "Recovery HD," if that's what it is, from loader + description. This is done because some OS X users are getting confused and + even upset over this detail, even though it's accurate, at least from an + EFI/rEFInd point of view. + +- Fixed memory management bug (introduced in 0.10.6) that caused error + messages to be displayed on some systems. + +0.10.6 (4/16/2017): +------------------- + +- Fixed bug in drivers that could cause filesystems to not be registered, + and perhaps other unknown problems. This manifested on 32-bit GNU-EFI + compiles, but in principle it could cause problems on 64-bit or TianoCore + builds, too. + +- Fixed bug in mvrefind that could cause it to fail to move the rEFInd + installation because it incorrectly converted the target directory to an + empty string if the target directory did not (yet) exist. + +- Added mm{arch}.efi as MokManager filename, and fb{arch}.efi to list + of boot loaders to be ignored. + +- New refind.conf token: extra_kernel_version_strings, which sets strings + that are treated something like digits for purposes of matching Linux + kernel and initrd filenames. + +- Don't set the video mode if the computer is already running in the + requested mode. This is a shot-in-the-dark attempt to fix problems with + Mac "retina" displays, which tend to get bumped down to a lower resolution + by rEFInd. + +0.10.5 (3/4/2017): +------------------ + +- Two improvements to initrd detection for Linux kernels: + - If multiple initrd files match the kernel's version number, the file + with more matching characters after the version number is used, rather + than the first initrd file found. + - The "%v" string, if present in the refind_linux.conf file's second + field, will be replaced by the kernel version number. Thus, you can + specify options like: + "Boot with standard initrd" "ro root=/dev/sda2 initrd=initrd-%v-std" + "Boot with debug initrd" "ro root=/dev/sda2 initrd=initrd-%v-debug" + This enables using multiple initrd files per kernel, to be used for + different purposes. + +- Minor code optimization. + +- Add new key mappings: Backspace (Delete on Mac keyboards) works the same + as Esc, and Tab works the same as F2/Insert/+. This is done for the + benefit of new Apple laptops that lack physical Esc and function keys. + +- Fix to refind-install to work better with disks other than /dev/sd? and + /dev/hd? devices. + +- Fixes to touch/tablet support to improve reliability. + 0.10.4 (10/9/2016): ------------------- diff -Nru refind-0.10.4/README.txt refind-0.11.2/README.txt --- refind-0.10.4/README.txt 2015-11-29 18:54:47.000000000 +0000 +++ refind-0.11.2/README.txt 2017-05-26 02:03:17.000000000 +0000 @@ -14,6 +14,7 @@ refind/drivers_x64/ Subdirectory containing x86-64 drivers keys/ Subdirectory containing MOKs refind-install Linux/MacOS installation script + refind-mkdefault Script to make rEFInd the default mkrlconf A script to create refind_linux.conf mvrefind A script to move a rEFInd installation README.txt This file diff -Nru refind-0.10.4/refind/apple.c refind-0.11.2/refind/apple.c --- refind-0.10.4/refind/apple.c 2016-02-01 02:19:49.000000000 +0000 +++ refind-0.11.2/refind/apple.c 2017-08-04 19:16:32.000000000 +0000 @@ -25,7 +25,7 @@ #include "screen.h" #include "apple.h" #include "mystrings.h" -#include "refit_call_wrapper.h" +#include "../include/refit_call_wrapper.h" CHAR16 gCsrStatus[256]; @@ -61,12 +61,7 @@ // on the Info page. If DisplayMessage is TRUE, displays the new value of // gCsrStatus on the screen for three seconds. VOID RecordgCsrStatus(UINT32 CsrStatus, BOOLEAN DisplayMessage) { - EG_PIXEL BGColor; - - BGColor.b = 255; - BGColor.g = 175; - BGColor.r = 100; - BGColor.a = 0; + EG_PIXEL BGColor = COLOR_LIGHTBLUE; switch (CsrStatus) { case SIP_ENABLED: @@ -79,7 +74,7 @@ SPrint(gCsrStatus, 255, L" System Integrity Protection status: 0x%02x", CsrStatus); } // switch if (DisplayMessage) { - egDisplayMessage(gCsrStatus, &BGColor); + egDisplayMessage(gCsrStatus, &BGColor, CENTER); PauseSeconds(3); } // if } // VOID RecordgCsrStatus() @@ -161,7 +156,7 @@ Status = EFI_OUT_OF_RESOURCES; Print(L"Out of resources in SetAppleOSInfo!\n"); } - if ((Status == EFI_SUCCESS) && (SetOs->Version == 2)) + if ((Status == EFI_SUCCESS) && (SetOs->Version >= 2)) Status = refit_call1_wrapper (SetOs->SetOsVendor, (CHAR8 *) "Apple Inc."); MyFreePool(AppleOSVersion); } // if (AppleOSVersion) diff -Nru refind-0.10.4/refind/config.c refind-0.11.2/refind/config.c --- refind-0.10.4/refind/config.c 2016-10-03 18:22:26.000000000 +0000 +++ refind-0.11.2/refind/config.c 2017-10-17 13:00:54.000000000 +0000 @@ -513,9 +513,7 @@ if (SelfVolume->VolName) { TempStr = SelfVolume->VolName ? StrDuplicate(SelfVolume->VolName) : NULL; } else { - TempStr = AllocateZeroPool(256 * sizeof(CHAR16)); - if (TempStr != NULL) - SPrint(TempStr, 255, L"fs%d", SelfVolume->VolNumber); + TempStr = GuidAsString(&(SelfVolume->PartGuid)); } // if/else } MergeStrings(&TempStr, SelfDirPath, L':'); @@ -523,11 +521,14 @@ GlobalConfig.DontScanDirs = TempStr; MyFreePool(GlobalConfig.DontScanFiles); GlobalConfig.DontScanFiles = StrDuplicate(DONT_SCAN_FILES); + MyFreePool(GlobalConfig.DontScanTools); + GlobalConfig.DontScanTools = NULL; MergeStrings(&(GlobalConfig.DontScanFiles), MOK_NAMES, L','); MergeStrings(&(GlobalConfig.DontScanFiles), FWUPDATE_NAMES, L','); MyFreePool(GlobalConfig.DontScanVolumes); GlobalConfig.DontScanVolumes = StrDuplicate(DONT_SCAN_VOLUMES); GlobalConfig.WindowsRecoveryFiles = StrDuplicate(WINDOWS_RECOVERY_FILES); + GlobalConfig.MacOSRecoveryFiles = StrDuplicate(MACOS_RECOVERY_FILES); if (GlobalConfig.DefaultSelection != NULL) { MyFreePool(GlobalConfig.DefaultSelection); GlobalConfig.DefaultSelection = NULL; @@ -620,6 +621,9 @@ } else if (MyStriCmp(TokenList[0], L"don't_scan_files") || MyStriCmp(TokenList[0], L"dont_scan_files")) { HandleStrings(TokenList, TokenCount, &(GlobalConfig.DontScanFiles)); + } else if (MyStriCmp(TokenList[0], L"don't_scan_tools") || MyStriCmp(TokenList[0], L"dont_scan_tools")) { + HandleStrings(TokenList, TokenCount, &(GlobalConfig.DontScanTools)); + } else if (MyStriCmp(TokenList[0], L"windows_recovery_files")) { HandleStrings(TokenList, TokenCount, &(GlobalConfig.WindowsRecoveryFiles)); @@ -628,6 +632,7 @@ } else if (MyStriCmp(TokenList[0], L"showtools")) { SetMem(GlobalConfig.ShowTools, NUM_TOOLS * sizeof(UINTN), 0); + GlobalConfig.HiddenTags = FALSE; for (i = 1; (i < TokenCount) && (i < NUM_TOOLS); i++) { FlagName = TokenList[i]; if (MyStriCmp(FlagName, L"shell")) { @@ -660,6 +665,9 @@ GlobalConfig.ShowTools[i - 1] = TAG_MEMTEST; } else if (MyStriCmp(FlagName, L"netboot")) { GlobalConfig.ShowTools[i - 1] = TAG_NETBOOT; + } else if (MyStriCmp(FlagName, L"hidden_tags")) { + GlobalConfig.ShowTools[i - 1] = TAG_HIDDEN; + GlobalConfig.HiddenTags = TRUE; } else { Print(L" unknown showtools flag: '%s'\n", FlagName); } @@ -679,14 +687,23 @@ } else if (MyStriCmp(TokenList[0], L"small_icon_size") && (TokenCount == 2)) { HandleInt(TokenList, TokenCount, &i); - if (i >= 32) + if (i >= 32) { GlobalConfig.IconSizes[ICON_SIZE_SMALL] = i; + HaveResized = TRUE; + } } else if (MyStriCmp(TokenList[0], L"big_icon_size") && (TokenCount == 2)) { HandleInt(TokenList, TokenCount, &i); if (i >= 32) { GlobalConfig.IconSizes[ICON_SIZE_BIG] = i; GlobalConfig.IconSizes[ICON_SIZE_BADGE] = i / 4; + HaveResized = TRUE; + } + + } else if (MyStriCmp(TokenList[0], L"mouse_size") && (TokenCount == 2)) { + HandleInt(TokenList, TokenCount, &i); + if (i >= DEFAULT_MOUSE_SIZE) { + GlobalConfig.IconSizes[ICON_SIZE_MOUSE] = i; } } else if (MyStriCmp(TokenList[0], L"selection_small")) { @@ -744,6 +761,9 @@ } else if (MyStriCmp(TokenList[0], L"fold_linux_kernels")) { GlobalConfig.FoldLinuxKernels = HandleBoolean(TokenList, TokenCount); + } else if (MyStriCmp(TokenList[0], L"extra_kernel_version_strings")) { + HandleStrings(TokenList, TokenCount, &(GlobalConfig.ExtraKernelVersionStrings)); + } else if (MyStriCmp(TokenList[0], L"max_tags")) { HandleInt(TokenList, TokenCount, &(GlobalConfig.MaxTags)); @@ -761,8 +781,25 @@ ReadConfig(TokenList[1]); } + } else if (MyStriCmp(TokenList[0], L"enable_mouse")) { + GlobalConfig.EnableMouse = HandleBoolean(TokenList, TokenCount); + if(GlobalConfig.EnableMouse) { + GlobalConfig.EnableTouch = FALSE; + } + } else if (MyStriCmp(TokenList[0], L"enable_touch")) { GlobalConfig.EnableTouch = HandleBoolean(TokenList, TokenCount); + if(GlobalConfig.EnableTouch) { + GlobalConfig.EnableMouse = FALSE; + } + + } else if (MyStriCmp(TokenList[0], L"mouse_speed") && (TokenCount == 2)) { + HandleInt(TokenList, TokenCount, &i); + if (i < 1) + i = 1; + if (i > 32) + i = 32; + GlobalConfig.MouseSpeed = i; } FreeTokenLine(&TokenList, &TokenCount); @@ -777,50 +814,6 @@ } } /* VOID ReadConfig() */ -// Finds a volume with the specified Identifier (a filesystem label, a -// partition name, a partition GUID, or a number followed by a colon). If -// found, sets *Volume to point to that volume. If not, leaves it unchanged. -// Returns TRUE if a match was found, FALSE if not. -static BOOLEAN FindVolume(REFIT_VOLUME **Volume, CHAR16 *Identifier) { - UINTN i = 0, CountedVolumes = 0, Length; - INTN Number = -1; - BOOLEAN Found = FALSE, IdIsGuid = FALSE; - EFI_GUID VolGuid, NullGuid = NULL_GUID_VALUE; - - VolGuid = StringAsGuid(Identifier); - Length = StrLen(Identifier); - if ((Length >= 2) && (Identifier[Length - 1] == L':') && - (Identifier[0] >= L'0') && (Identifier[0] <= L'9')) { - Number = (INTN) Atoi(Identifier); - } else if (IsGuid(Identifier)) { - IdIsGuid = TRUE; - } - while ((i < VolumesCount) && (!Found)) { - if (Number >= 0) { // User specified a volume by number - if (Volumes[i]->IsReadable) { - if (CountedVolumes == Number) { - *Volume = Volumes[i]; - Found = TRUE; - } - CountedVolumes++; - } // if - } else { // User specified a volume by label or GUID - if (MyStriCmp(Identifier, Volumes[i]->VolName) || MyStriCmp(Identifier, Volumes[i]->PartName)) { - *Volume = Volumes[i]; - Found = TRUE; - } // if - if (IdIsGuid && !Found) { - if (GuidsAreEqual(&VolGuid, &(Volumes[i]->PartGuid)) && !GuidsAreEqual(&NullGuid, &(Volumes[i]->PartGuid))) { - *Volume = Volumes[i]; - Found = TRUE; - } // if - } // if - } // if/else - i++; - } // while() - return (Found); -} // static VOID FindVolume() - static VOID AddSubmenu(LOADER_ENTRY *Entry, REFIT_FILE *File, REFIT_VOLUME *Volume, CHAR16 *Title) { REFIT_MENU_SCREEN *SubScreen; LOADER_ENTRY *SubEntry; @@ -841,7 +834,7 @@ if (MyStriCmp(TokenList[0], L"loader") && (TokenCount > 1)) { // set the boot loader filename MyFreePool(SubEntry->LoaderPath); SubEntry->LoaderPath = StrDuplicate(TokenList[1]); - SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath); + SubEntry->Volume = Volume; } else if (MyStriCmp(TokenList[0], L"volume") && (TokenCount > 1)) { if (FindVolume(&Volume, TokenList[1])) { @@ -850,7 +843,7 @@ 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; + SubEntry->Volume = Volume; } // if volume is readable } // if match found @@ -913,14 +906,14 @@ SPrint(Entry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", CurrentVolume->VolName); Entry->me.Row = 0; Entry->me.BadgeImage = CurrentVolume->VolBadgeImage; - Entry->VolName = CurrentVolume->VolName; + Entry->Volume = CurrentVolume; + Entry->DiscoveryType = DISCOVERY_TYPE_MANUAL; // Parse the config file to add options for a single stanza, terminating when the token // is "}" or when the end of file is reached. while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StrCmp(TokenList[0], L"}") != 0)) { if (MyStriCmp(TokenList[0], L"loader") && (TokenCount > 1)) { // set the boot loader filename Entry->LoaderPath = StrDuplicate(TokenList[1]); - Entry->DevicePath = FileDevicePath(CurrentVolume->DeviceHandle, Entry->LoaderPath); SetLoaderDefaults(Entry, TokenList[1], CurrentVolume); MyFreePool(Entry->LoadOptions); Entry->LoadOptions = NULL; // Discard default options, if any @@ -933,7 +926,7 @@ 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; + Entry->Volume = CurrentVolume; } // if volume is readable } // if match found @@ -1139,14 +1132,9 @@ // you pass this function the filename of the Linux kernel, initial RAM disk, or other // file in the target directory, and this function finds the file with a name in the // comma-delimited list of names specified by LINUX_OPTIONS_FILENAMES within that -// directory and loads it. This function tries multiple files because I originally -// used the filename linux.conf, but close on the heels of that decision, the Linux -// kernel developers decided to use that name for a similar purpose, but with a -// different file format. Thus, I'm migrating rEFInd to use the name refind_linux.conf, -// but I want a migration period in which both names are used. -// If a rEFInd options file can't be found, try to generate minimal options from -// /etc/fstab on the same volume as the kernel. This typically works only if the -// kernel is being read from the Linux root filesystem. +// directory and loads it. If a rEFInd options file can't be found, try to generate +// minimal options from /etc/fstab on the same volume as the kernel. This typically +// works only if the kernel is being read from the Linux root filesystem. // // The return value is a pointer to the REFIT_FILE handle for the file, or NULL if // it wasn't found. diff -Nru refind-0.10.4/refind/config.h refind-0.11.2/refind/config.h --- refind-0.10.4/refind/config.h 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/refind/config.h 2017-08-01 00:26:48.000000000 +0000 @@ -69,8 +69,16 @@ } REFIT_FILE; #define CONFIG_FILE_NAME L"refind.conf" -// Note: Below is combined with MOK_NAMES to make default -#define DONT_SCAN_FILES L"shim.efi,shim-fedora.efi,shimx64.efi,PreLoader.efi,TextMode.efi,ebounce.efi,GraphicsConsole.efi,bootmgr.efi" +// Note: Below is combined with MOK_NAMES and FWUPDATE_NAMES to make default +#if defined (EFIX64) +#define DONT_SCAN_FILES L"shim.efi,shim-fedora.efi,shim-centos.efi,shimx64.efi,PreLoader.efi,TextMode.efi,ebounce.efi,GraphicsConsole.efi,bootmgr.efi,fbx64.efi" +#elif defined(EFI32) +#define DONT_SCAN_FILES L"shim.efi,shim-fedora.efi,shim-centos.efi,shimx64.efi,PreLoader.efi,TextMode.efi,ebounce.efi,GraphicsConsole.efi,bootmgr.efi,fbia32.efi" +#elif defined(EFIAARCH64) +#define DONT_SCAN_FILES L"shim.efi,shim-fedora.efi,shim-centos.efi,shimx64.efi,PreLoader.efi,TextMode.efi,ebounce.efi,GraphicsConsole.efi,bootmgr.efi,fbaa64.efi" +#else +#define DONT_SCAN_FILES L"shim.efi,shim-fedora.efi,shim-centos.efi,shimx64.efi,PreLoader.efi,TextMode.efi,ebounce.efi,GraphicsConsole.efi,bootmgr.efi" +#endif #define DONT_SCAN_VOLUMES L"LRS_ESP" #define ALSO_SCAN_DIRS L"boot,@/boot" diff -Nru refind-0.10.4/refind/driver_support.c refind-0.11.2/refind/driver_support.c --- refind-0.10.4/refind/driver_support.c 2016-01-27 01:35:36.000000000 +0000 +++ refind-0.11.2/refind/driver_support.c 2017-10-09 17:34:43.000000000 +0000 @@ -48,7 +48,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Modifications copyright (c) 2012-2016 Roderick W. Smith + * Modifications copyright (c) 2012-2017 Roderick W. Smith * * Modifications distributed under the terms of the GNU General Public * License (GPL) version 3 (GPLv3), or (at your option) any later version. @@ -81,39 +81,38 @@ #define DRIVER_DIRS L"drivers,drivers_ia32" #elif defined (EFIAARCH64) #define DRIVER_DIRS L"drivers,drivers_aa64" +#else +#define DRIVER_DIRS L"drivers" #endif -#ifdef __MAKEWITH_GNUEFI // Following "global" constants are from EDK2's AutoGen.c.... -EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -EFI_GUID gEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 }}; -EFI_GUID gEfiDriverConfiguration2ProtocolGuid = { 0xBFD7DC1D, 0x24F1, 0x40D9, { 0x82, 0xE7, 0x2E, 0x09, 0xBB, 0x6B, 0x4E, 0xBE }}; -EFI_GUID gEfiDriverConfigurationProtocolGuid = { 0x107A772B, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; -EFI_GUID gEfiDriverDiagnosticsProtocolGuid = { 0x0784924F, 0xE296, 0x11D4, { 0x9A, 0x49, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; -EFI_GUID gEfiDriverDiagnostics2ProtocolGuid = { 0x4D330321, 0x025F, 0x4AAC, { 0x90, 0xD8, 0x5E, 0xD9, 0x00, 0x17, 0x3B, 0x63 }}; -EFI_GUID gEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; -EFI_GUID gEfiComponentName2ProtocolGuid = { 0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14 }}; -EFI_GUID gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -EFI_GUID gEfiDiskIoProtocolGuid = { 0xCE345171, 0xBA0B, 0x11D2, { 0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -EFI_GUID gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -EFI_GUID gEfiSimpleFileSystemProtocolGuid = { 0x964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gMyEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gMyEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 }}; +EFI_GUID gMyEfiDriverConfigurationProtocolGuid = { 0x107A772B, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; +EFI_GUID gMyEfiDriverDiagnosticsProtocolGuid = { 0x0784924F, 0xE296, 0x11D4, { 0x9A, 0x49, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; +EFI_GUID gMyEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; +EFI_GUID gMyEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gMyEfiDiskIoProtocolGuid = { 0xCE345171, 0xBA0B, 0x11D2, { 0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gMyEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gMyEfiSimpleFileSystemProtocolGuid = { 0x964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; -struct EFI_FILE_PROTOCOL; +#ifdef __MAKEWITH_GNUEFI +struct MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; +struct MY_EFI_FILE_PROTOCOL; typedef EFI_STATUS -(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)( - IN struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, - OUT struct EFI_FILE_PROTOCOL **Root +(EFIAPI *MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)( + IN struct MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT struct MY_EFI_FILE_PROTOCOL **Root ); -typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { +typedef struct _MY_MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { UINT64 Revision; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume; -} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume; +} MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; -typedef struct _EFI_FILE_PROTOCOL { +typedef struct _MY_EFI_FILE_PROTOCOL { UINT64 Revision; EFI_FILE_OPEN Open; EFI_FILE_CLOSE Close; @@ -125,16 +124,20 @@ EFI_FILE_GET_INFO GetInfo; EFI_FILE_SET_INFO SetInfo; EFI_FILE_FLUSH Flush; -} EFI_FILE_PROTOCOL; +} MY_EFI_FILE_PROTOCOL; -typedef struct _EFI_BLOCK_IO_PROTOCOL { +typedef struct _MY_EFI_BLOCK_IO_PROTOCOL { UINT64 Revision; EFI_BLOCK_IO_MEDIA *Media; EFI_BLOCK_RESET Reset; EFI_BLOCK_READ ReadBlocks; EFI_BLOCK_WRITE WriteBlocks; EFI_BLOCK_FLUSH FlushBlocks; -} EFI_BLOCK_IO_PROTOCOL; +} MY_EFI_BLOCK_IO_PROTOCOL; +#else /* Make with Tianocore */ +#define MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL +#define MY_EFI_FILE_PROTOCOL EFI_FILE_PROTOCOL +#define MY_EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL #endif /* LibScanHandleDatabase() is used by rEFInd's driver-loading code (inherited @@ -230,27 +233,27 @@ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { - if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) == 0) { + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gMyEfiLoadedImageProtocolGuid) == 0) { (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_IMAGE_HANDLE; } - if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) == 0) { + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gMyEfiDriverBindingProtocolGuid) == 0) { (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE; } - if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) == 0) { + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gMyEfiDriverConfigurationProtocolGuid) == 0) { (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE; } - if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) == 0) { + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gMyEfiDriverDiagnosticsProtocolGuid) == 0) { (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE; } - if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) == 0) { + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gMyEfiComponentNameProtocolGuid) == 0) { (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE; } - if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) == 0) { + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gMyEfiDevicePathProtocolGuid) == 0) { (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DEVICE_HANDLE; } // @@ -451,8 +454,8 @@ UINTN Index; UINTN OpenInfoIndex; EFI_HANDLE *Handles = NULL; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; - EFI_BLOCK_IO_PROTOCOL *BlockIo; + MY_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + MY_EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; UINTN OpenInfoCount; EFI_HANDLE DriverHandleList[2]; @@ -462,7 +465,7 @@ // Status = refit_call5_wrapper(gBS->LocateHandleBuffer, ByProtocol, - &gEfiDiskIoProtocolGuid, + &gMyEfiDiskIoProtocolGuid, NULL, &HandleCount, &Handles); @@ -481,7 +484,7 @@ // Status = refit_call3_wrapper(gBS->HandleProtocol, Handles[Index], - &gEfiBlockIoProtocolGuid, + &gMyEfiBlockIoProtocolGuid, (VOID **) &BlockIo); if (EFI_ERROR (Status)) continue; @@ -492,9 +495,9 @@ // If SimpleFileSystem is already produced - skip it, this is ok // Status = refit_call3_wrapper(gBS->HandleProtocol, - Handles[Index], - &gEfiSimpleFileSystemProtocolGuid, - (VOID **) &Fs); + Handles[Index], + &gMyEfiSimpleFileSystemProtocolGuid, + (VOID **) &Fs); if (Status == EFI_SUCCESS) continue; @@ -504,7 +507,7 @@ // Status = refit_call4_wrapper(gBS->OpenProtocolInformation, Handles[Index], - &gEfiDiskIoProtocolGuid, + &gMyEfiDiskIoProtocolGuid, &OpenInfo, &OpenInfoCount); if (EFI_ERROR (Status)) @@ -550,9 +553,8 @@ SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName); NumFound++; - Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName), - L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE, TRUE); - } + Status = StartEFIImage(SelfVolume, FileName, L"", DirEntry->FileName, 0, FALSE, TRUE); + } // while Status = DirIterClose(&DirIter); if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { SPrint(FileName, 255, L"while scanning the %s directory", Path); @@ -566,7 +568,8 @@ // directories specified by the user in the "scan_driver_dirs" configuration // file line. // Originally from rEFIt's main.c (BSD), but modified since then (GPLv3). -VOID LoadDrivers(VOID) { +// Returns TRUE if any drivers are loaded, FALSE otherwise. +BOOLEAN LoadDrivers(VOID) { CHAR16 *Directory, *SelfDirectory; UINTN i = 0, Length, NumFound = 0; @@ -595,4 +598,5 @@ // connect all devices if (NumFound > 0) ConnectAllDriversToAllControllers(); -} /* VOID LoadDrivers() */ + return (NumFound > 0); +} /* BOOLEAN LoadDrivers() */ diff -Nru refind-0.10.4/refind/driver_support.h refind-0.11.2/refind/driver_support.h --- refind-0.10.4/refind/driver_support.h 2016-01-24 20:23:33.000000000 +0000 +++ refind-0.11.2/refind/driver_support.h 2017-10-09 17:31:29.000000000 +0000 @@ -54,6 +54,6 @@ ); EFI_STATUS ConnectAllDriversToAllControllers(VOID); VOID ConnectFilesystemDriver(EFI_HANDLE DriverHandle); -VOID LoadDrivers(VOID); +BOOLEAN LoadDrivers(VOID); #endif diff -Nru refind-0.10.4/refind/global.h refind-0.11.2/refind/global.h --- refind-0.10.4/refind/global.h 2016-10-03 18:23:59.000000000 +0000 +++ refind-0.11.2/refind/global.h 2017-10-09 17:23:58.000000000 +0000 @@ -53,7 +53,7 @@ #endif #include "../EfiLib/GenericBdsLib.h" -#include "libeg.h" +#include "../libeg/libeg.h" #define REFIT_DEBUG (0) @@ -77,7 +77,8 @@ #define TAG_NETBOOT (17) #define TAG_CSR_ROTATE (18) #define TAG_FWUPDATE_TOOL (19) -#define NUM_TOOLS (20) +#define TAG_HIDDEN (20) +#define NUM_TOOLS (21) #define NUM_SCAN_OPTIONS 10 @@ -90,15 +91,16 @@ #define GRAPHICS_FOR_GRUB 8 #define GRAPHICS_FOR_WINDOWS 16 -// Load types -#define TYPE_EFI 1 -#define TYPE_LEGACY 2 - // Type of legacy (BIOS) boot support detected #define LEGACY_TYPE_NONE 0 #define LEGACY_TYPE_MAC 1 #define LEGACY_TYPE_UEFI 2 +// How was a loader added to the menu? +#define DISCOVERY_TYPE_UNKNOWN 0 +#define DISCOVERY_TYPE_AUTO 1 +#define DISCOVERY_TYPE_MANUAL 2 + #ifdef __MAKEWITH_GNUEFI // // define BBS Device Types @@ -143,14 +145,27 @@ // Sizes of the default icons; badges are 1/4 the big icon size #define DEFAULT_SMALL_ICON_SIZE 48 #define DEFAULT_BIG_ICON_SIZE 128 +#define DEFAULT_MOUSE_SIZE 16 // Codes for types of icon sizes; used for indexing into GlobalConfig.IconSizes[] #define ICON_SIZE_BADGE 0 #define ICON_SIZE_SMALL 1 #define ICON_SIZE_BIG 2 +#define ICON_SIZE_MOUSE 3 + +// Minimum horizontal resolution for a screen to be consider high-DPI +#define HIDPI_MIN 1921 // Names of binaries that can manage MOKs.... +#if defined (EFIX64) +#define MOK_NAMES L"MokManager.efi,HashTool.efi,HashTool-signed.efi,KeyTool.efi,KeyTool-signed.efi,mmx64.efi" +#elif defined(EFI32) +#define MOK_NAMES L"MokManager.efi,HashTool.efi,HashTool-signed.efi,KeyTool.efi,KeyTool-signed.efi,mmia32.efi" +#elif defined(EFIAARCH64) +#define MOK_NAMES L"MokManager.efi,HashTool.efi,HashTool-signed.efi,KeyTool.efi,KeyTool-signed.efi,mmaa64.efi" +#else #define MOK_NAMES L"MokManager.efi,HashTool.efi,HashTool-signed.efi,KeyTool.efi,KeyTool-signed.efi" +#endif // Names of binaries that can update firmware.... #if defined (EFIX64) #define FWUPDATE_NAMES L"fwupx64.efi" @@ -167,7 +182,9 @@ // Directories to search for memtest86.... #define MEMTEST_LOCATIONS L"EFI\\tools,EFI\\tools\\memtest86,EFI\\tools\\memtest,EFI\\memtest86,EFI\\memtest" // Files that may be Windows recovery files -#define WINDOWS_RECOVERY_FILES L"EFI\\Microsoft\\Boot\\LrsBootmgr.efi,Recovery:\\EFI\\BOOT\\bootx64.efi,Recovery:\\EFI\\BOOT\\bootia32.efi" +#define WINDOWS_RECOVERY_FILES L"EFI\\Microsoft\\Boot\\LrsBootmgr.efi,Recovery:\\EFI\\BOOT\\bootx64.efi,Recovery:\\EFI\\BOOT\\bootia32.efi,\\EFI\\OEM\\Boot\\bootmgfw.efi" +// Files that may be macOS recovery files +#define MACOS_RECOVERY_FILES L"com.apple.recovery.boot\\boot.efi" // Filename patterns that identify EFI boot loaders. Note that a single case (either L"*.efi" or // L"*.EFI") is fine for most systems; but Gigabyte's buggy Hybrid EFI does a case-sensitive @@ -197,6 +214,9 @@ #define NULL_GUID_VALUE { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; #define REFIND_GUID_VALUE { 0x36D08FA7, 0xCF0B, 0x42F5, {0x8F, 0x14, 0x68, 0xDF, 0x73, 0xED, 0x37, 0x40} }; +// Configuration file variables +#define KERNEL_VERSION L"%v" + // // global definitions // @@ -231,11 +251,10 @@ EFI_GUID PartGuid; EFI_GUID PartTypeGuid; BOOLEAN IsMarkedReadOnly; - UINTN VolNumber; EG_IMAGE *VolIconImage; EG_IMAGE *VolBadgeImage; UINTN DiskKind; - BOOLEAN IsAppleLegacy; +// BOOLEAN IsAppleLegacy; BOOLEAN HasBootCode; CHAR16 *OSIconName; CHAR16 *OSName; @@ -278,13 +297,13 @@ REFIT_MENU_ENTRY me; CHAR16 *Title; CHAR16 *LoaderPath; - CHAR16 *VolName; - EFI_DEVICE_PATH *DevicePath; + REFIT_VOLUME *Volume; BOOLEAN UseGraphicsMode; BOOLEAN Enabled; CHAR16 *LoadOptions; CHAR16 *InitrdPath; // Linux stub loader only CHAR8 OSType; + UINTN DiscoveryType; } LOADER_ENTRY; typedef struct { @@ -301,7 +320,9 @@ BOOLEAN DeepLegacyScan; BOOLEAN EnableAndLockVMX; BOOLEAN FoldLinuxKernels; + BOOLEAN EnableMouse; BOOLEAN EnableTouch; + BOOLEAN HiddenTags; UINTN RequestedScreenWidth; UINTN RequestedScreenHeight; UINTN BannerBottomEdge; @@ -313,7 +334,8 @@ UINTN LegacyType; UINTN ScanDelay; UINTN ScreensaverTime; - UINTN IconSizes[3]; + UINTN MouseSpeed; + UINTN IconSizes[4]; UINTN BannerScale; REFIT_VOLUME *DiscoveredRoot; EFI_DEVICE_PATH *SelfDevicePath; @@ -327,9 +349,12 @@ CHAR16 *DontScanVolumes; CHAR16 *DontScanDirs; CHAR16 *DontScanFiles; + CHAR16 *DontScanTools; CHAR16 *WindowsRecoveryFiles; + CHAR16 *MacOSRecoveryFiles; CHAR16 *DriverDirs; CHAR16 *IconsDir; + CHAR16 *ExtraKernelVersionStrings; CHAR16 *SpoofOSXVersion; UINT32_LIST *CsrValues; UINTN ShowTools[NUM_TOOLS]; @@ -353,16 +378,13 @@ extern EFI_GUID gEfiLegacyBootProtocolGuid; extern EFI_GUID gEfiGlobalVariableGuid; -EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, - IN CHAR16 *LoadOptions, IN UINTN LoaderType, - IN CHAR16 *ImageTitle, IN CHAR8 OSType, - OUT UINTN *ErrorInStep, - IN BOOLEAN Verbose, - IN BOOLEAN IsDriver); -EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, - IN CHAR16 *LoadOptions, IN UINTN LoaderType, - IN CHAR16 *ImageTitle, IN CHAR8 OSType, - OUT UINTN *ErrorInStep, +extern BOOLEAN HaveResized; + +EFI_STATUS StartEFIImage(IN REFIT_VOLUME *Volume, + IN CHAR16 *Filename, + IN CHAR16 *LoadOptions, + IN CHAR16 *ImageTitle, + IN CHAR8 OSType, IN BOOLEAN Verbose, IN BOOLEAN IsDriver); LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry); @@ -373,6 +395,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume); LOADER_ENTRY * AddPreparedLoaderEntry(LOADER_ENTRY *Entry); VOID StoreLoaderName(IN CHAR16 *Name); +VOID RescanAll(BOOLEAN DisplayMessage); #endif diff -Nru refind-0.10.4/refind/icns.c refind-0.11.2/refind/icns.c --- refind-0.10.4/refind/icns.c 2016-04-24 16:20:54.000000000 +0000 +++ refind-0.11.2/refind/icns.c 2017-08-11 20:59:13.000000000 +0000 @@ -58,6 +58,7 @@ { NULL, L"func_exit", ICON_SIZE_SMALL }, { NULL, L"func_firmware", ICON_SIZE_SMALL }, { NULL, L"func_csr_rotate", ICON_SIZE_SMALL }, + { NULL, L"func_hidden", ICON_SIZE_SMALL }, { NULL, L"tool_shell", ICON_SIZE_SMALL }, { NULL, L"tool_part", ICON_SIZE_SMALL }, { NULL, L"tool_rescue", ICON_SIZE_SMALL }, @@ -71,6 +72,7 @@ { NULL, L"vol_external", ICON_SIZE_BADGE }, { NULL, L"vol_optical", ICON_SIZE_BADGE }, { NULL, L"vol_net", ICON_SIZE_BADGE }, + { NULL, L"mouse", ICON_SIZE_MOUSE } }; EG_IMAGE * BuiltinIcon(IN UINTN Id) diff -Nru refind-0.10.4/refind/icns.h refind-0.11.2/refind/icns.h --- refind-0.10.4/refind/icns.h 2016-04-24 16:18:56.000000000 +0000 +++ refind-0.11.2/refind/icns.h 2017-08-04 13:15:08.000000000 +0000 @@ -61,20 +61,22 @@ #define BUILTIN_ICON_FUNC_EXIT (3) #define BUILTIN_ICON_FUNC_FIRMWARE (4) #define BUILTIN_ICON_FUNC_CSR_ROTATE (5) -#define BUILTIN_ICON_TOOL_SHELL (6) -#define BUILTIN_ICON_TOOL_PART (7) -#define BUILTIN_ICON_TOOL_RESCUE (8) -#define BUILTIN_ICON_TOOL_APPLE_RESCUE (9) -#define BUILTIN_ICON_TOOL_WINDOWS_RESCUE (10) -#define BUILTIN_ICON_TOOL_MOK_TOOL (11) -#define BUILTIN_ICON_TOOL_FWUPDATE (12) -#define BUILTIN_ICON_TOOL_MEMTEST (13) -#define BUILTIN_ICON_TOOL_NETBOOT (14) -#define BUILTIN_ICON_VOL_INTERNAL (15) -#define BUILTIN_ICON_VOL_EXTERNAL (16) -#define BUILTIN_ICON_VOL_OPTICAL (17) -#define BUILTIN_ICON_VOL_NET (18) -#define BUILTIN_ICON_COUNT (19) +#define BUILTIN_ICON_FUNC_HIDDEN (6) +#define BUILTIN_ICON_TOOL_SHELL (7) +#define BUILTIN_ICON_TOOL_PART (8) +#define BUILTIN_ICON_TOOL_RESCUE (9) +#define BUILTIN_ICON_TOOL_APPLE_RESCUE (10) +#define BUILTIN_ICON_TOOL_WINDOWS_RESCUE (11) +#define BUILTIN_ICON_TOOL_MOK_TOOL (12) +#define BUILTIN_ICON_TOOL_FWUPDATE (13) +#define BUILTIN_ICON_TOOL_MEMTEST (14) +#define BUILTIN_ICON_TOOL_NETBOOT (15) +#define BUILTIN_ICON_VOL_INTERNAL (16) +#define BUILTIN_ICON_VOL_EXTERNAL (17) +#define BUILTIN_ICON_VOL_OPTICAL (18) +#define BUILTIN_ICON_VOL_NET (19) +#define BUILTIN_ICON_MOUSE (20) +#define BUILTIN_ICON_COUNT (21) #endif diff -Nru refind-0.10.4/refind/icns.h.orig refind-0.11.2/refind/icns.h.orig --- refind-0.10.4/refind/icns.h.orig 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/refind/icns.h.orig 2017-08-04 13:13:37.000000000 +0000 @@ -0,0 +1,99 @@ +/* + * refit/icns.h + * Icon management header file + * + * Copyright (c) 2006-2009 Christoph Pfisterer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Christoph Pfisterer nor the names of the + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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-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 + * with this source code or binaries made from it. + * + */ + +#ifndef __ICNS_H_ +#define __ICNS_H_ + +// +// icns loader module +// + +EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconName, BOOLEAN BootLogo); + +EG_IMAGE * DummyImage(IN UINTN PixelSize); + +EG_IMAGE * BuiltinIcon(IN UINTN Id); + +#define BUILTIN_ICON_FUNC_ABOUT (0) +#define BUILTIN_ICON_FUNC_RESET (1) +#define BUILTIN_ICON_FUNC_SHUTDOWN (2) +#define BUILTIN_ICON_FUNC_EXIT (3) +#define BUILTIN_ICON_FUNC_FIRMWARE (4) +#define BUILTIN_ICON_FUNC_CSR_ROTATE (5) +<<<<<<< HEAD +#define BUILTIN_ICON_FUNC_HIDDEN (6) +#define BUILTIN_ICON_TOOL_SHELL (7) +#define BUILTIN_ICON_TOOL_PART (8) +#define BUILTIN_ICON_TOOL_RESCUE (9) +#define BUILTIN_ICON_TOOL_APPLE_RESCUE (10) +#define BUILTIN_ICON_TOOL_WINDOWS_RESCUE (11) +#define BUILTIN_ICON_TOOL_MOK_TOOL (12) +#define BUILTIN_ICON_TOOL_FWUPDATE (13) +#define BUILTIN_ICON_TOOL_MEMTEST (14) +#define BUILTIN_ICON_TOOL_NETBOOT (15) +#define BUILTIN_ICON_VOL_INTERNAL (16) +#define BUILTIN_ICON_VOL_EXTERNAL (17) +#define BUILTIN_ICON_VOL_OPTICAL (18) +#define BUILTIN_ICON_VOL_NET (19) +======= +#define BUILTIN_ICON_TOOL_SHELL (6) +#define BUILTIN_ICON_TOOL_PART (7) +#define BUILTIN_ICON_TOOL_RESCUE (8) +#define BUILTIN_ICON_TOOL_APPLE_RESCUE (9) +#define BUILTIN_ICON_TOOL_WINDOWS_RESCUE (10) +#define BUILTIN_ICON_TOOL_MOK_TOOL (11) +#define BUILTIN_ICON_TOOL_FWUPDATE (12) +#define BUILTIN_ICON_TOOL_MEMTEST (13) +#define BUILTIN_ICON_TOOL_NETBOOT (14) +#define BUILTIN_ICON_VOL_INTERNAL (15) +#define BUILTIN_ICON_VOL_EXTERNAL (16) +#define BUILTIN_ICON_VOL_OPTICAL (17) +#define BUILTIN_ICON_VOL_NET (18) +#define BUILTIN_ICON_MOUSE (19) +>>>>>>> d63734581c19715b3dc13ab89c520def8d5c4566 +#define BUILTIN_ICON_COUNT (20) + +#endif + +/* EOF */ diff -Nru refind-0.10.4/refind/legacy.c refind-0.11.2/refind/legacy.c --- refind-0.10.4/refind/legacy.c 2016-01-26 14:14:38.000000000 +0000 +++ refind-0.11.2/refind/legacy.c 2017-10-09 02:59:15.000000000 +0000 @@ -60,13 +60,13 @@ #include "legacy.h" #include "lib.h" #include "menu.h" -#include "refit_call_wrapper.h" +#include "../include/refit_call_wrapper.h" #include "screen.h" -#include "syslinux_mbr.h" +#include "../include/syslinux_mbr.h" #include "mystrings.h" #include "../EfiLib/BdsHelper.h" #include "../EfiLib/legacy.h" -#include "Handle.h" +#include "../include/Handle.h" extern REFIT_MENU_ENTRY MenuEntryReturn; extern REFIT_MENU_SCREEN MainMenu; @@ -76,6 +76,8 @@ #define DevicePathProtocol gEfiDevicePathProtocolGuid #endif +EFI_GUID EfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }}; + static EFI_STATUS ActivateMbrPartition(IN EFI_BLOCK_IO *BlockIO, IN UINTN PartitionIndex) { EFI_STATUS Status; @@ -321,6 +323,78 @@ #define MAX_DISCOVERED_PATHS (16) +// Launch a BIOS boot loader (Mac mode) +static EFI_STATUS StartLegacyImageList(IN EFI_DEVICE_PATH **DevicePaths, + IN CHAR16 *LoadOptions, + OUT UINTN *ErrorInStep) +{ + EFI_STATUS Status, ReturnStatus; + EFI_HANDLE ChildImageHandle; + EFI_LOADED_IMAGE *ChildLoadedImage = NULL; + UINTN DevicePathIndex; + CHAR16 ErrorInfo[256]; + CHAR16 *FullLoadOptions = NULL; + + if (ErrorInStep != NULL) + *ErrorInStep = 0; + + // set load options + if (LoadOptions != NULL) { + FullLoadOptions = StrDuplicate(LoadOptions); + } // if (LoadOptions != NULL) + Print(L"Starting legacy loader\nUsing load options '%s'\n", FullLoadOptions ? FullLoadOptions : L""); + + // load the image into memory + ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty + for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) { + ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex], + NULL, 0, &ChildImageHandle); + if (ReturnStatus != EFI_NOT_FOUND) { + break; + } + } // for + SPrint(ErrorInfo, 255, L"while loading legacy loader"); + if (CheckError(Status, ErrorInfo)) { + if (ErrorInStep != NULL) + *ErrorInStep = 1; + goto bailout; + } + + ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol, + (VOID **) &ChildLoadedImage); + if (CheckError(Status, L"while getting a LoadedImageProtocol handle")) { + if (ErrorInStep != NULL) + *ErrorInStep = 2; + goto bailout_unload; + } + ChildLoadedImage->LoadOptions = (VOID *)FullLoadOptions; + ChildLoadedImage->LoadOptionsSize = FullLoadOptions ? ((UINT32)StrLen(FullLoadOptions) + 1) * sizeof(CHAR16) : 0; + // turn control over to the image + // TODO: (optionally) re-enable the EFI watchdog timer! + + // close open file handles + UninitRefitLib(); + ReturnStatus = Status = refit_call3_wrapper(BS->StartImage, ChildImageHandle, NULL, NULL); + + // control returns here when the child image calls Exit() + SPrint(ErrorInfo, 255, L"returned from legacy loader"); + if (CheckError(Status, ErrorInfo)) { + if (ErrorInStep != NULL) + *ErrorInStep = 3; + } + + // re-open file handles + ReinitRefitLib(); + +bailout_unload: + // unload the image, we don't care if it works or not... + Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle); + +bailout: + MyFreePool(FullLoadOptions); + return ReturnStatus; +} /* EFI_STATUS StartLegacyImageList() */ + VOID StartLegacy(IN LEGACY_ENTRY *Entry, IN CHAR16 *SelectionName) { EFI_STATUS Status; @@ -346,7 +420,7 @@ ExtractLegacyLoaderPaths(DiscoveredPathList, MAX_DISCOVERED_PATHS, LegacyLoaderList); StoreLoaderName(SelectionName); - Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, TYPE_LEGACY, L"legacy loader", 0, &ErrorInStep, TRUE, FALSE); + Status = StartLegacyImageList(DiscoveredPathList, Entry->LoadOptions, &ErrorInStep); if (Status == EFI_NOT_FOUND) { if (ErrorInStep == 1) { Print(L"\nPlease make sure that you have the latest firmware update installed.\n"); @@ -463,7 +537,7 @@ // prepare the menu entry Entry = AllocateZeroPool(sizeof(LEGACY_ENTRY)); Entry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16)); - SPrint(Entry->me.Title, 255, L"Boot legacy target %s", LegacyDescription); + SPrint(Entry->me.Title, 255, L"Boot legacy OS from %s", LegacyDescription); Entry->me.Tag = TAG_LEGACY_UEFI; Entry->me.Row = 0; Entry->me.ShortcutLetter = ShortcutLetter; @@ -538,7 +612,7 @@ } // if // Grab the boot order - BootOrder = BdsLibGetVariableAndSize(L"BootOrder", &gEfiGlobalVariableGuid, &BootOrderSize); + BootOrder = BdsLibGetVariableAndSize(L"BootOrder", &EfiGlobalVariableGuid, &BootOrderSize); if (BootOrder == NULL) { BootOrderSize = 0; } @@ -582,10 +656,12 @@ ShowVolume = FALSE; HideIfOthersFound = FALSE; - if (Volume->IsAppleLegacy) { - ShowVolume = TRUE; - HideIfOthersFound = TRUE; - } else if (Volume->HasBootCode) { +// if (Volume->IsAppleLegacy) { +// Print(L" Volume is Apple legacy\n"); +// ShowVolume = TRUE; +// HideIfOthersFound = TRUE; +// } else + if (Volume->HasBootCode) { ShowVolume = TRUE; if (Volume->BlockIO == Volume->WholeDiskBlockIO && Volume->BlockIOOffset == 0 && diff -Nru refind-0.10.4/refind/lib.c refind-0.11.2/refind/lib.c --- refind-0.10.4/refind/lib.c 2016-10-06 14:04:14.000000000 +0000 +++ refind-0.11.2/refind/lib.c 2017-10-09 17:25:19.000000000 +0000 @@ -34,7 +34,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Modifications copyright (c) 2012-2015 Roderick W. Smith + * Modifications copyright (c) 2012-2017 Roderick W. Smith * * Modifications distributed under the terms of the GNU General Public * License (GPL) version 3 (GPLv3), or (at your option) any later version. @@ -120,37 +120,38 @@ // in pathnames, because some user inputs can produce duplicate directory // separators, and because we want consistent start and end slashes for // directory comparisons. A special case: If the PathName refers to root, -// return "/", since some firmware implementations flake out if this -// isn't present. +// but is non-empty, return "\", since some firmware implementations flake +// out if this isn't present. VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) { - CHAR16 *NewName; - UINTN i, Length, FinalChar = 0; - BOOLEAN LastWasSlash = FALSE; - - Length = StrLen(PathName); - NewName = AllocateZeroPool(sizeof(CHAR16) * (Length + 2)); - if (NewName != NULL) { - for (i = 0; i < Length; i++) { - if ((PathName[i] == L'/') || (PathName[i] == L'\\')) { - if ((!LastWasSlash) && (FinalChar != 0)) - NewName[FinalChar++] = L'\\'; - LastWasSlash = TRUE; + UINTN Source = 0, Dest = 0; + + if ((PathName == NULL) || (PathName[0] == '\0')) + return; + + while (PathName[Source] != '\0') { + if ((PathName[Source] == L'/') || (PathName[Source] == L'\\')) { + if (Dest == 0) { // Skip slash if to first position + Source++; } else { - NewName[FinalChar++] = PathName[i]; - LastWasSlash = FALSE; + PathName[Dest] = L'\\'; + do { // Skip subsequent slashes + Source++; + } while ((PathName[Source] == L'/') || (PathName[Source] == L'\\')); + Dest++; } // if/else - } // for - NewName[FinalChar] = 0; - if ((FinalChar > 0) && (NewName[FinalChar - 1] == L'\\')) - NewName[--FinalChar] = 0; - if (FinalChar == 0) { - NewName[0] = L'\\'; - NewName[1] = 0; - } - // Copy the transformed name back.... - StrCpy(PathName, NewName); - FreePool(NewName); - } // if allocation OK + } else { // Regular character; copy it straight.... + PathName[Dest] = PathName[Source]; + Source++; + Dest++; + } // if/else + } // while() + if ((Dest > 0) && (PathName[Dest - 1] == L'\\')) + Dest--; + PathName[Dest] = L'\0'; + if (PathName[0] == L'\0') { + PathName[0] = L'\\'; + PathName[1] = L'\0'; + } } // CleanUpPathNameSlashes() // Splits an EFI device path into device and filename components. For instance, if InString is @@ -211,7 +212,7 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle) { EFI_STATUS Status; - CHAR16 *DevicePathAsString, *Temp; + CHAR16 *DevicePathAsString, *Temp = NULL; SelfImageHandle = ImageHandle; Status = refit_call3_wrapper(BS->HandleProtocol, SelfImageHandle, &LoadedImageProtocol, (VOID **) &SelfLoadedImage); @@ -495,7 +496,7 @@ } else { // none of these features; presume it's ext2... Volume->FSType = FS_TYPE_EXT2; } - CopyMem(&(Volume->VolUuid), Buffer + 1024 + 104, sizeof(EFI_GUID)); + CopyMem(&(Volume->VolUuid), Buffer + 1024 + 120, sizeof(EFI_GUID)); return; } } // search for ext2/3/4 magic @@ -865,7 +866,12 @@ } // if (GUIDs match && automounting OK) Volume->IsMarkedReadOnly = ((PartInfo->attributes & GPT_READ_ONLY) > 0); } // if (PartInfo exists) - } // if (GPT disk) + } else { + // TODO: Better to assign a random GUID to MBR partitions, but I couldn't + // find an EFI function to do this. The below GUID is just one that I + // generated in Linux. + Volume->PartGuid = StringAsGuid(L"92a6c61f-7130-49b9-b05c-8d7e7b039127"); + } // if/else (GPT disk) } // if (disk device) } // VOID SetPartGuid() @@ -940,11 +946,11 @@ 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) == 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 @@ -1082,7 +1088,7 @@ UINTN HandleIndex; UINTN VolumeIndex, VolumeIndex2; UINTN PartitionIndex; - UINTN SectorSum, i, VolNumber = 0; + UINTN SectorSum, i; UINT8 *SectorBuffer1, *SectorBuffer2; EFI_GUID *UuidList; EFI_GUID NullUuid = NULL_GUID_VALUE; @@ -1116,10 +1122,6 @@ } // if } // for } // if - if (Volume->IsReadable) - Volume->VolNumber = VolNumber++; - else - Volume->VolNumber = VOL_UNREADABLE; AddListElement((VOID ***) &Volumes, &VolumesCount, Volume); @@ -1407,7 +1409,7 @@ FreePool(DirIter->LastFileInfo); DirIter->LastFileInfo = NULL; } - if (DirIter->CloseDirHandle) + if ((DirIter->CloseDirHandle) && (DirIter->DirHandle->Close)) refit_call1_wrapper(DirIter->DirHandle->Close, DirIter->DirHandle); return DirIter->LastStatus; } @@ -1563,6 +1565,9 @@ UINTN i = 0; BOOLEAN Found = FALSE; + if (!loadpath || !DeviceVolume || !loader) + return; + MyFreePool(*loader); MyFreePool(*DeviceVolume); *DeviceVolume = NULL; @@ -1570,6 +1575,10 @@ *loader = SplitDeviceString(DeviceString); while ((i < VolumesCount) && (!Found)) { + if (Volumes[i]->DevicePath == NULL) { + i++; + continue; + } VolumeDeviceString = DevicePathToStr(Volumes[i]->DevicePath); Temp = SplitDeviceString(VolumeDeviceString); if (MyStriCmp(DeviceString, VolumeDeviceString)) { @@ -1647,6 +1656,39 @@ MyFreePool(Temp); } // VOID SplitPathName() +// Finds a volume with the specified Identifier (a filesystem label, a +// partition name, or a partition GUID). If found, sets *Volume to point +// to that volume. If not, leaves it unchanged. +// Returns TRUE if a match was found, FALSE if not. +BOOLEAN FindVolume(REFIT_VOLUME **Volume, CHAR16 *Identifier) { + UINTN i = 0; + BOOLEAN Found = FALSE; + + while ((i < VolumesCount) && (!Found)) { + if (VolumeMatchesDescription(Volumes[i], Identifier)) { + *Volume = Volumes[i]; + Found = TRUE; + } // if + i++; + } // while() + return (Found); +} // static VOID FindVolume() + +// Returns TRUE if Description matches Volume's VolName, PartName, or (once +// transformed) PartGuid fields, FALSE otherwise (or if either pointer is NULL) +BOOLEAN VolumeMatchesDescription(REFIT_VOLUME *Volume, CHAR16 *Description) { + EFI_GUID TargetVolGuid = NULL_GUID_VALUE; + + if ((Volume == NULL) || (Description == NULL)) + return FALSE; + if (IsGuid(Description)) { + TargetVolGuid = StringAsGuid(Description); + return GuidsAreEqual(&TargetVolGuid, &(Volume->PartGuid)); + } else { + return (MyStriCmp(Description, Volume->VolName) || MyStriCmp(Description, Volume->PartName)); + } +} // BOOLEAN VolumeMatchesDescription() + // Returns TRUE if specified Volume, Directory, and Filename correspond to an // element in the comma-delimited List, FALSE otherwise. Note that Directory and // Filename must *NOT* include a volume or path specification (that's part of @@ -1662,44 +1704,21 @@ while (!Found && (OneElement = FindCommaDelimited(List, i++))) { Found = TRUE; SplitPathName(OneElement, &TargetVolName, &TargetPath, &TargetFilename); - VolumeNumberToName(Volume, &TargetVolName); - if (((TargetVolName != NULL) && ((Volume == NULL) || (!MyStriCmp(TargetVolName, Volume->VolName)))) || + if (((TargetVolName != NULL) && (!VolumeMatchesDescription(Volume, TargetVolName))) || ((TargetPath != NULL) && (!MyStriCmp(TargetPath, Directory))) || ((TargetFilename != NULL) && (!MyStriCmp(TargetFilename, Filename)))) { Found = FALSE; } // if MyFreePool(OneElement); } // while + MyFreePool(TargetVolName); + MyFreePool(TargetPath); + MyFreePool(TargetFilename); } // if - MyFreePool(TargetVolName); - MyFreePool(TargetPath); - MyFreePool(TargetFilename); return Found; } // BOOLEAN FilenameIn() -// If *VolName is of the form "fs#", where "#" is a number, and if Volume points -// to this volume number, returns with *VolName changed to the volume name, as -// stored in the Volume data structure. -// Returns TRUE if this substitution was made, FALSE otherwise. -BOOLEAN VolumeNumberToName(REFIT_VOLUME *Volume, CHAR16 **VolName) { - BOOLEAN MadeSubstitution = FALSE; - UINTN VolNum; - - if ((VolName == NULL) || (*VolName == NULL)) - return FALSE; - - if ((StrLen(*VolName) > 2) && (*VolName[0] == L'f') && (*VolName[1] == L's') && (*VolName[2] >= L'0') && (*VolName[2] <= L'9')) { - VolNum = Atoi(*VolName + 2); - if (VolNum == Volume->VolNumber) { - MyFreePool(*VolName); - *VolName = StrDuplicate(Volume->VolName); - MadeSubstitution = TRUE; - } // if - } // if - return MadeSubstitution; -} // BOOLEAN VolumeMatchesNumber() - // Implement FreePool the way it should have been done to begin with, so that // it doesn't throw an ASSERT message if fed a NULL pointer.... VOID MyFreePool(IN VOID *Pointer) { diff -Nru refind-0.10.4/refind/lib.h refind-0.11.2/refind/lib.h --- refind-0.10.4/refind/lib.h 2016-01-20 14:27:31.000000000 +0000 +++ refind-0.11.2/refind/lib.h 2017-10-09 17:25:28.000000000 +0000 @@ -125,8 +125,9 @@ VOID FindVolumeAndFilename(IN EFI_DEVICE_PATH *loadpath, OUT REFIT_VOLUME **DeviceVolume, OUT CHAR16 **loader); BOOLEAN SplitVolumeAndFilename(IN OUT CHAR16 **Path, OUT CHAR16 **VolName); VOID SplitPathName(CHAR16 *InPath, CHAR16 **VolName, CHAR16 **Path, CHAR16 **Filename); +BOOLEAN FindVolume(REFIT_VOLUME **Volume, CHAR16 *Identifier); +BOOLEAN VolumeMatchesDescription(REFIT_VOLUME *Volume, CHAR16 *Description); BOOLEAN FilenameIn(IN REFIT_VOLUME *Volume, IN CHAR16 *Directory, IN CHAR16 *Filename, IN CHAR16 *List); -BOOLEAN VolumeNumberToName(REFIT_VOLUME *Volume, CHAR16 **VolName); VOID MyFreePool(IN OUT VOID *Pointer); BOOLEAN EjectMedia(VOID); diff -Nru refind-0.10.4/refind/line_edit.c refind-0.11.2/refind/line_edit.c --- refind-0.10.4/refind/line_edit.c 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/refind/line_edit.c 2016-10-28 13:01:22.000000000 +0000 @@ -211,7 +211,7 @@ } refit_call2_wrapper(ST->ConOut->EnableCursor, ST->ConOut, FALSE); - FreePool(print); - FreePool(line); + MyFreePool(print); + MyFreePool(line); return enter; } /* BOOLEAN line_edit() */ diff -Nru refind-0.10.4/refind/main.c refind-0.11.2/refind/main.c --- refind-0.10.4/refind/main.c 2016-10-06 14:04:48.000000000 +0000 +++ refind-0.11.2/refind/main.c 2017-10-17 13:00:10.000000000 +0000 @@ -34,7 +34,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Modifications copyright (c) 2012-2016 Roderick W. Smith + * Modifications copyright (c) 2012-2017 Roderick W. Smith * * Modifications distributed under the terms of the GNU General Public * License (GPL) version 3 (GPLv3), or (at your option) any later version. @@ -62,6 +62,7 @@ #include "lib.h" #include "icns.h" #include "menu.h" +#include "pointer.h" #include "mok.h" #include "gpt.h" #include "apple.h" @@ -70,6 +71,7 @@ #include "driver_support.h" #include "../include/Handle.h" #include "../include/refit_call_wrapper.h" +#include "../include/version.h" #include "../EfiLib/BdsHelper.h" #include "../EfiLib/legacy.h" @@ -152,22 +154,63 @@ static REFIT_MENU_ENTRY MenuEntryShutdown = { L"Shut Down Computer", TAG_SHUTDOWN, 1, 0, 'U', NULL, NULL, NULL }; REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryExit = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryManageHidden = { L"Manage Hidden Tags Menu", TAG_HIDDEN, 1, 0, 0, NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryFirmware = { L"Reboot to Computer Setup Utility", TAG_FIRMWARE, 1, 0, 0, NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryRotateCsr = { L"Change SIP Policy", TAG_CSR_ROTATE, 1, 0, 0, NULL, NULL, NULL }; 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" }; + L"Insert, Tab, or F2 for more options; Esc or Backspace 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, TRUE, FALSE, FALSE, TRUE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, - 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, - 0, 0, { DEFAULT_BIG_ICON_SIZE / 4, DEFAULT_SMALL_ICON_SIZE, DEFAULT_BIG_ICON_SIZE }, - BANNER_NOSCALE, NULL, NULL, NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY, - TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, TAG_FWUPDATE_TOOL, - 0, 0, 0, 0, 0, 0, 0, 0 } +REFIT_CONFIG GlobalConfig = { /* TextOnly = */ FALSE, + /* ScanAllLinux = */ TRUE, + /* DeepLegacyScan = */ FALSE, + /* EnableAndLockVMX = */ FALSE, + /* FoldLinuxKernels = */ TRUE, + /* EnableMouse = */ FALSE, + /* EnableTouch = */ FALSE, + /* HiddenTags = */ TRUE, + /* RequestedScreenWidth = */ 0, + /* RequestedScreenHeight = */ 0, + /* BannerBottomEdge = */ 0, + /* RequestedTextMode = */ DONT_CHANGE_TEXT_MODE, + /* Timeout = */ 20, + /* HideUIFlags = */ 0, + /* MaxTags = */ 0, + /* GraphicsFor = */ GRAPHICS_FOR_OSX, + /* LegacyType = */ LEGACY_TYPE_MAC, + /* ScanDelay = */ 0, + /* ScreensaverTime = */ 0, + /* MouseSpeed = */ 4, + /* IconSizes = */ { DEFAULT_BIG_ICON_SIZE / 4, + DEFAULT_SMALL_ICON_SIZE, + DEFAULT_BIG_ICON_SIZE, + DEFAULT_MOUSE_SIZE }, + /* BannerScale = */ BANNER_NOSCALE, + /* *DiscoveredRoot = */ NULL, + /* *SelfDevicePath = */ NULL, + /* *BannerFileName = */ NULL, + /* *ScreenBackground = */ NULL, + /* *ConfigFilename = */ CONFIG_FILE_NAME, + /* *SelectionSmallFileName = */ NULL, + /* *SelectionBigFileName = */ NULL, + /* *DefaultSelection = */ NULL, + /* *AlsoScan = */ NULL, + /* *DontScanVolumes = */ NULL, + /* *DontScanDirs = */ NULL, + /* *DontScanFiles = */ NULL, + /* *DontScanTools = */ NULL, + /* *WindowsRecoveryFiles = */ NULL, + /* *MacOSRecoveryFiles = */ NULL, + /* *DriverDirs = */ NULL, + /* *IconsDir = */ NULL, + /* *ExtraKernelVersionStrings = */ NULL, + /* *SpoofOSXVersion = */ NULL, + /* CsrValues = */ NULL, + /* ShowTools = */ { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY, + TAG_MOK_TOOL, TAG_ABOUT, TAG_HIDDEN, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, + TAG_FWUPDATE_TOOL, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; EFI_GUID GlobalGuid = EFI_GLOBAL_VARIABLE; @@ -197,7 +240,7 @@ AddMenuInfoLine(&AboutMenu, PoolPrint(L"rEFInd Version %s", REFIND_VERSION)); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); - AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2016 Roderick W. Smith"); + AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2017 Roderick W. Smith"); AddMenuInfoLine(&AboutMenu, L"Portions Copyright (c) Intel Corporation and others"); AddMenuInfoLine(&AboutMenu, L"Distributed under the terms of the GNU GPLv3 license"); AddMenuInfoLine(&AboutMenu, L""); @@ -272,7 +315,7 @@ if ((RootDir == NULL) || (FileName == NULL)) { // Assume valid here, because Macs produce NULL RootDir (& maybe FileName) // when launching from a Firewire drive. This should be handled better, but - // fix would have to be in StartEFIImageList() and/or in FindVolumeAndFilename(). + // fix would have to be in StartEFIImage() and/or in FindVolumeAndFilename(). return TRUE; } // if @@ -296,103 +339,90 @@ } // BOOLEAN IsValidLoader() // Launch an EFI binary. -EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, - IN CHAR16 *LoadOptions, IN UINTN LoaderType, - IN CHAR16 *ImageTitle, IN CHAR8 OSType, - OUT UINTN *ErrorInStep, - IN BOOLEAN Verbose, - IN BOOLEAN IsDriver) +EFI_STATUS StartEFIImage(IN REFIT_VOLUME *Volume, + IN CHAR16 *Filename, + IN CHAR16 *LoadOptions, + IN CHAR16 *ImageTitle, + IN CHAR8 OSType, + IN BOOLEAN Verbose, + IN BOOLEAN IsDriver) { EFI_STATUS Status, ReturnStatus; EFI_HANDLE ChildImageHandle, ChildImageHandle2; + EFI_DEVICE_PATH *DevicePath; EFI_LOADED_IMAGE *ChildLoadedImage = NULL; - REFIT_VOLUME *Volume = NULL; - UINTN DevicePathIndex; CHAR16 ErrorInfo[256]; CHAR16 *FullLoadOptions = NULL; - CHAR16 *Filename = NULL; CHAR16 *Temp; - if (ErrorInStep != NULL) - *ErrorInStep = 0; - // set load options if (LoadOptions != NULL) { FullLoadOptions = StrDuplicate(LoadOptions); - if ((LoaderType == TYPE_EFI) && (OSType == 'M')) { + if (OSType == 'M') { MergeStrings(&FullLoadOptions, L" ", 0); // NOTE: That last space is also added by the EFI shell and seems to be significant // when passing options to Apple's boot.efi... } // if } // if (LoadOptions != NULL) if (Verbose) - Print(L"Starting %s\nUsing load options '%s'\n", ImageTitle, FullLoadOptions ? FullLoadOptions : L""); + Print(L"Starting %s\nUsing load options '%s'\n", ImageTitle, FullLoadOptions ? FullLoadOptions : L""); // load the image into memory ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty - for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) { - FindVolumeAndFilename(DevicePaths[DevicePathIndex], &Volume, &Filename); - // Some EFIs crash if attempting to load driver for invalid architecture, so - // protect for this condition; but sometimes Volume comes back NULL, so provide - // an exception. (TODO: Handle this special condition better.) - if ((LoaderType == TYPE_LEGACY) || (Volume == NULL) || IsValidLoader(Volume->RootDir, Filename)) { - if (Filename && (LoaderType != TYPE_LEGACY)) { - Temp = PoolPrint(L"\\%s %s", Filename, FullLoadOptions ? FullLoadOptions : L""); - if (Temp != NULL) { - MyFreePool(FullLoadOptions); - FullLoadOptions = Temp; - } - } // if (Filename) - - // NOTE: Below commented-out line could be more efficient if file were read ahead of - // time and passed as a pre-loaded image to LoadImage(), but it doesn't work on my - // 32-bit Mac Mini or my 64-bit Intel box when launching a Linux kernel; the - // kernel returns a "Failed to handle fs_proto" error message. - // 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 (secure_mode() && ShimLoaded()) { - // Load ourself into memory. This is a trick to work around a bug in Shim 0.8, - // which ties itself into the BS->LoadImage() and BS->StartImage() functions and - // then unregisters itself from the EFI system table when its replacement - // StartImage() function is called *IF* the previous LoadImage() was for the same - // program. The result is that rEFInd can validate only the first program it - // launches (often a filesystem driver). Loading a second program (rEFInd itself, - // here, to keep it smaller than a kernel) works around this problem. See the - // replacements.c file in Shim, and especially its start_image() function, for - // the source of the problem. - // NOTE: This doesn't check the return status or handle errors. It could - // conceivably do weird things if, say, rEFInd were on a USB drive that the - // user pulls before launching a program. - refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, GlobalConfig.SelfDevicePath, - NULL, 0, &ChildImageHandle2); + // Some EFIs crash if attempting to load driver for invalid architecture, so + // protect for this condition; but sometimes Volume comes back NULL, so provide + // an exception. (TODO: Handle this special condition better.) + if (IsValidLoader(Volume->RootDir, Filename)) { + if (Filename) { + Temp = PoolPrint(L"\\%s %s", Filename, FullLoadOptions ? FullLoadOptions : L""); + if (Temp != NULL) { + MyFreePool(FullLoadOptions); + FullLoadOptions = Temp; } - } else { - Print(L"Invalid loader file!\n"); - ReturnStatus = EFI_LOAD_ERROR; - } - if (ReturnStatus != EFI_NOT_FOUND) { - break; + } // if (Filename) + + DevicePath = FileDevicePath(Volume->DeviceHandle, Filename); + // NOTE: Below commented-out line could be more efficient if file were read ahead of + // time and passed as a pre-loaded image to LoadImage(), but it doesn't work on my + // 32-bit Mac Mini or my 64-bit Intel box when launching a Linux kernel; the + // kernel returns a "Failed to handle fs_proto" error message. + // TODO: Track down the cause of this error and fix it, if possible. + // ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePath, + // ImageData, ImageSize, &ChildImageHandle); + ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePath, + NULL, 0, &ChildImageHandle); + if (secure_mode() && ShimLoaded()) { + // Load ourself into memory. This is a trick to work around a bug in Shim 0.8, + // which ties itself into the BS->LoadImage() and BS->StartImage() functions and + // then unregisters itself from the EFI system table when its replacement + // StartImage() function is called *IF* the previous LoadImage() was for the same + // program. The result is that rEFInd can validate only the first program it + // launches (often a filesystem driver). Loading a second program (rEFInd itself, + // here, to keep it smaller than a kernel) works around this problem. See the + // replacements.c file in Shim, and especially its start_image() function, for + // the source of the problem. + // NOTE: This doesn't check the return status or handle errors. It could + // conceivably do weird things if, say, rEFInd were on a USB drive that the + // user pulls before launching a program. + refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, GlobalConfig.SelfDevicePath, + NULL, 0, &ChildImageHandle2); } - } // for + } else { + Print(L"Invalid loader file!\n"); + ReturnStatus = EFI_LOAD_ERROR; + } if ((Status == EFI_ACCESS_DENIED) || (Status == EFI_SECURITY_VIOLATION)) { WarnSecureBootError(ImageTitle, Verbose); goto bailout; } SPrint(ErrorInfo, 255, L"while loading %s", ImageTitle); if (CheckError(Status, ErrorInfo)) { - if (ErrorInStep != NULL) - *ErrorInStep = 1; goto bailout; } ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol, (VOID **) &ChildLoadedImage); if (CheckError(Status, L"while getting a LoadedImageProtocol handle")) { - if (ErrorInStep != NULL) - *ErrorInStep = 2; goto bailout_unload; } ChildLoadedImage->LoadOptions = (VOID *)FullLoadOptions; @@ -406,10 +436,7 @@ // control returns here when the child image calls Exit() SPrint(ErrorInfo, 255, L"returned from %s", ImageTitle); - if (CheckError(Status, ErrorInfo)) { - if (ErrorInStep != NULL) - *ErrorInStep = 3; - } + CheckError(Status, ErrorInfo); if (IsDriver) { // Below should have no effect on most systems, but works // around bug with some EFIs that prevents filesystem drivers @@ -428,21 +455,7 @@ bailout: MyFreePool(FullLoadOptions); return ReturnStatus; -} /* EFI_STATUS StartEFIImageList() */ - -EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, - IN CHAR16 *LoadOptions, IN UINTN LoaderType, - IN CHAR16 *ImageTitle, IN CHAR8 OSType, - OUT UINTN *ErrorInStep, - IN BOOLEAN Verbose, - IN BOOLEAN IsDriver) -{ - EFI_DEVICE_PATH *DevicePaths[2]; - - DevicePaths[0] = DevicePath; - DevicePaths[1] = NULL; - return StartEFIImageList(DevicePaths, LoadOptions, LoaderType, ImageTitle, OSType, ErrorInStep, Verbose, IsDriver); -} /* static EFI_STATUS StartEFIImage() */ +} /* EFI_STATUS StartEFIImage() */ // From gummiboot: Reboot the computer into its built-in user interface static EFI_STATUS RebootIntoFirmware(VOID) { @@ -511,16 +524,14 @@ static VOID StartLoader(LOADER_ENTRY *Entry, CHAR16 *SelectionName) { - UINTN ErrorInStep = 0; - if (GlobalConfig.EnableAndLockVMX) { DoEnableAndLockVMX(); } BeginExternalScreen(Entry->UseGraphicsMode, L"Booting OS"); StoreLoaderName(SelectionName); - StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI, - Basename(Entry->LoaderPath), Entry->OSType, &ErrorInStep, !Entry->UseGraphicsMode, FALSE); + StartEFIImage(Entry->Volume, Entry->LoaderPath, Entry->LoadOptions, + Basename(Entry->LoaderPath), Entry->OSType, !Entry->UseGraphicsMode, FALSE); FinishExternalScreen(); } @@ -530,13 +541,16 @@ // For instance, if LoaderPath is \EFI\kernels\bzImage-3.3.0.efi, and if \EFI\kernels // has a file called initramfs-3.3.0.img, this function will return the string // '\EFI\kernels\initramfs-3.3.0.img'. If the directory ALSO contains the file -// initramfs-3.3.0-rc7.img or initramfs-13.3.0.img, those files will NOT match; -// however, initmine-3.3.0.img might match. (FindInitrd() returns the first match it -// finds.) Thus, care should be taken to avoid placing duplicate matching files in -// the kernel's directory. +// initramfs-3.3.0-rc7.img or initramfs-13.3.0.img, those files will NOT match. +// If more than one initrd file matches the extracted version string, the one +// that matches more characters AFTER (actually, from the start of) the version +// string is used. // If no matching init file can be found, returns NULL. static CHAR16 * FindInitrd(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) { CHAR16 *InitrdName = NULL, *FileName, *KernelVersion, *InitrdVersion, *Path; + CHAR16 *KernelPostNum, *InitrdPostNum; + UINTN MaxSharedChars, SharedChars; + STRING_LIST *InitrdNames = NULL, *FinalInitrdName = NULL, *CurrentInitrdName = NULL, *MaxSharedInitrd; REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry; @@ -555,20 +569,44 @@ // building the InitrdName later.... if ((StrLen(Path) > 0) && (Path[StrLen(Path) - 1] != L'\\')) MergeStrings(&Path, L"\\", 0); - while ((DirIterNext(&DirIter, 2, L"init*", &DirEntry)) && (InitrdName == NULL)) { + while (DirIterNext(&DirIter, 2, L"init*", &DirEntry)) { InitrdVersion = FindNumbers(DirEntry->FileName); - if (KernelVersion != NULL) { - if (MyStriCmp(InitrdVersion, KernelVersion)) { - InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName); - } // if + if (((KernelVersion != NULL) && (MyStriCmp(InitrdVersion, KernelVersion))) || + ((KernelVersion == NULL) && (InitrdVersion == NULL))) { + CurrentInitrdName = AllocateZeroPool(sizeof(STRING_LIST)); + if (InitrdNames == NULL) + InitrdNames = FinalInitrdName = CurrentInitrdName; + if (CurrentInitrdName) { + CurrentInitrdName->Value = PoolPrint(L"%s%s", Path, DirEntry->FileName); + if (CurrentInitrdName != FinalInitrdName) { + FinalInitrdName->Next = CurrentInitrdName; + FinalInitrdName = CurrentInitrdName; + } // if + } // if + } // if + } // while + if (InitrdNames) { + if (InitrdNames->Next == NULL) { + InitrdName = StrDuplicate(InitrdNames -> Value); } else { - if (InitrdVersion == NULL) { - InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName); - } // if + MaxSharedInitrd = CurrentInitrdName = InitrdNames; + MaxSharedChars = 0; + while (CurrentInitrdName != NULL) { + KernelPostNum = MyStrStr(LoaderPath, KernelVersion); + InitrdPostNum = MyStrStr(CurrentInitrdName->Value, KernelVersion); + SharedChars = NumCharsInCommon(KernelPostNum, InitrdPostNum); + if (SharedChars > MaxSharedChars) { + MaxSharedChars = SharedChars; + MaxSharedInitrd = CurrentInitrdName; + } // if + // TODO: Compute number of shared characters & compare with max. + CurrentInitrdName = CurrentInitrdName->Next; + } + if (MaxSharedInitrd) + InitrdName = StrDuplicate(MaxSharedInitrd->Value); } // if/else - MyFreePool(InitrdVersion); - } // while - DirIterClose(&DirIter); + } // if + DeleteStringList(InitrdNames); // Note: Don't FreePool(FileName), since Basename returns a pointer WITHIN the string it's passed. MyFreePool(KernelVersion); @@ -658,8 +696,7 @@ NewEntry->OSType = 0; if (Entry != NULL) { NewEntry->LoaderPath = (Entry->LoaderPath) ? StrDuplicate(Entry->LoaderPath) : NULL; - NewEntry->VolName = (Entry->VolName) ? StrDuplicate(Entry->VolName) : NULL; - NewEntry->DevicePath = Entry->DevicePath; + NewEntry->Volume = Entry->Volume; NewEntry->UseGraphicsMode = Entry->UseGraphicsMode; NewEntry->LoadOptions = (Entry->LoadOptions) ? StrDuplicate(Entry->LoadOptions) : NULL; NewEntry->InitrdPath = (Entry->InitrdPath) ? StrDuplicate(Entry->InitrdPath) : NULL; @@ -703,7 +740,7 @@ if (SubScreen != NULL) { SubScreen->Title = AllocateZeroPool(sizeof(CHAR16) * 256); SPrint(SubScreen->Title, 255, L"Boot Options for %s on %s", - (Entry->Title != NULL) ? Entry->Title : FileName, Entry->VolName); + (Entry->Title != NULL) ? Entry->Title : FileName, Entry->Volume->VolName); SubScreen->TitleImage = Entry->me.Image; // default entry SubEntry = InitializeLoaderEntry(Entry); @@ -730,7 +767,7 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN GenerateReturn) { REFIT_MENU_SCREEN *SubScreen; LOADER_ENTRY *SubEntry; - CHAR16 *InitrdName; + CHAR16 *InitrdName, *KernelVersion = NULL; CHAR16 DiagsFileName[256]; REFIT_FILE *File; UINTN TokenCount; @@ -744,11 +781,11 @@ SubScreen = InitializeSubScreen(Entry); // loader-specific submenu entries - if (Entry->OSType == 'M') { // entries for Mac OS X + if (Entry->OSType == 'M') { // entries for macOS #if defined(EFIX64) SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot Mac OS X with a 64-bit kernel"; + SubEntry->me.Title = L"Boot macOS with a 64-bit kernel"; SubEntry->LoadOptions = L"arch=x86_64"; SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -756,7 +793,7 @@ SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot Mac OS X with a 32-bit kernel"; + SubEntry->me.Title = L"Boot macOS with a 32-bit kernel"; SubEntry->LoadOptions = L"arch=i386"; SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -766,7 +803,7 @@ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_SINGLEUSER)) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot Mac OS X in verbose mode"; + SubEntry->me.Title = L"Boot macOS in verbose mode"; SubEntry->UseGraphicsMode = FALSE; SubEntry->LoadOptions = L"-v"; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -775,7 +812,7 @@ #if defined(EFIX64) SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot Mac OS X in verbose mode (64-bit)"; + SubEntry->me.Title = L"Boot macOS in verbose mode (64-bit)"; SubEntry->UseGraphicsMode = FALSE; SubEntry->LoadOptions = L"-v arch=x86_64"; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -783,7 +820,7 @@ SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot Mac OS X in verbose mode (32-bit)"; + SubEntry->me.Title = L"Boot macOS in verbose mode (32-bit)"; SubEntry->UseGraphicsMode = FALSE; SubEntry->LoadOptions = L"-v arch=i386"; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -792,7 +829,7 @@ SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot Mac OS X in single user mode"; + SubEntry->me.Title = L"Boot macOS in single user mode"; SubEntry->UseGraphicsMode = FALSE; SubEntry->LoadOptions = L"-v -s"; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -802,7 +839,7 @@ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_SAFEMODE)) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot Mac OS X in safe mode"; + SubEntry->me.Title = L"Boot macOS in safe mode"; SubEntry->UseGraphicsMode = FALSE; SubEntry->LoadOptions = L"-v -x"; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -817,7 +854,7 @@ SubEntry->me.Title = L"Run Apple Hardware Test"; MyFreePool(SubEntry->LoaderPath); SubEntry->LoaderPath = StrDuplicate(DiagsFileName); - SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath); + SubEntry->Volume = Volume; SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } // if @@ -828,6 +865,8 @@ if (File != NULL) { InitrdName = FindInitrd(Entry->LoaderPath, Volume); TokenCount = ReadTokenLine(File, &TokenList); + KernelVersion = FindNumbers(Entry->LoaderPath); + ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion); // first entry requires special processing, since it was initially set // up with a default title but correct options by InitializeSubScreen(), // earlier.... @@ -837,6 +876,7 @@ } // if FreeTokenLine(&TokenList, &TokenCount); while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { + ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion); SubEntry = InitializeLoaderEntry(Entry); SubEntry->me.Title = TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux"); MyFreePool(SubEntry->LoadOptions); @@ -845,6 +885,7 @@ SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } // while + MyFreePool(KernelVersion); MyFreePool(InitrdName); MyFreePool(File); } // if @@ -922,14 +963,17 @@ // 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, *FullOptions = NULL; + CHAR16 *Options = NULL, *InitrdName, *FullOptions = NULL, *KernelVersion; Options = GetFirstOptionsFromFile(LoaderPath, Volume); InitrdName = FindInitrd(LoaderPath, Volume); + KernelVersion = FindNumbers(InitrdName); + ReplaceSubstring(&Options, KERNEL_VERSION, KernelVersion); FullOptions = AddInitrdToOptions(Options, InitrdName); MyFreePool(Options); MyFreePool(InitrdName); + MyFreePool(KernelVersion); return (FullOptions); } // static CHAR16 * GetMainLinuxOptions() @@ -1032,7 +1076,7 @@ MergeStrings(&OSIconName, L"refind", L','); Entry->OSType = 'R'; ShortcutLetter = 'R'; - } else if (MyStriCmp(LoaderPath, MACOSX_LOADER_PATH)) { + } else if (StriSubCmp(MACOSX_LOADER_PATH, LoaderPath)) { MergeStrings(&OSIconName, L"mac", L','); Entry->OSType = 'M'; ShortcutLetter = 'M'; @@ -1085,13 +1129,14 @@ CleanUpPathNameSlashes(LoaderPath); Entry = InitializeLoaderEntry(NULL); + Entry->DiscoveryType = DISCOVERY_TYPE_AUTO; if (Entry != NULL) { Entry->Title = StrDuplicate((LoaderTitle != NULL) ? LoaderTitle : LoaderPath); Entry->me.Title = AllocateZeroPool(sizeof(CHAR16) * 256); // Extra space at end of Entry->me.Title enables searching on Volume->VolName even if another volume // name is identical except for something added to the end (e.g., VolB1 vs. VolB12). // Note: Volume->VolName will be NULL for network boot programs. - if (Volume->VolName) + if ((Volume->VolName) && (!MyStriCmp(Volume->VolName, L"Recovery HD"))) SPrint(Entry->me.Title, 255, L"Boot %s from %s ", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath, Volume->VolName); else SPrint(Entry->me.Title, 255, L"Boot %s ", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath); @@ -1103,8 +1148,7 @@ Entry->LoaderPath = NULL; } MergeStrings(&(Entry->LoaderPath), LoaderPath, 0); - Entry->VolName = Volume->VolName; - Entry->DevicePath = FileDevicePath(Volume->DeviceHandle, Entry->LoaderPath); + Entry->Volume = Volume; SetLoaderDefaults(Entry, LoaderPath, Volume); GenerateSubScreen(Entry, Volume, SubScreenReturn); AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); @@ -1116,7 +1160,8 @@ // Add a Linux kernel as a submenu entry for another (pre-existing) Linux kernel entry. static VOID AddKernelToSubmenu(LOADER_ENTRY * TargetLoader, CHAR16 *FileName, REFIT_VOLUME *Volume) { REFIT_FILE *File; - CHAR16 **TokenList = NULL, *InitrdName, *SubmenuName = NULL, *VolName = NULL, *Path = NULL, *Title; + CHAR16 **TokenList = NULL, *InitrdName, *SubmenuName = NULL, *VolName = NULL; + CHAR16 *Path = NULL, *Title, *KernelVersion; REFIT_MENU_SCREEN *SubScreen; LOADER_ENTRY *SubEntry; UINTN TokenCount; @@ -1125,7 +1170,9 @@ if (File != NULL) { SubScreen = TargetLoader->me.SubScreen; InitrdName = FindInitrd(FileName, Volume); + KernelVersion = FindNumbers(FileName); while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { + ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion); SubEntry = InitializeLoaderEntry(TargetLoader); SplitPathName(FileName, &VolName, &Path, &SubmenuName); MergeStrings(&SubmenuName, L": ", '\0'); @@ -1138,7 +1185,7 @@ MyFreePool(SubEntry->LoaderPath); SubEntry->LoaderPath = StrDuplicate(FileName); CleanUpPathNameSlashes(SubEntry->LoaderPath); - SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath); + SubEntry->Volume = Volume; FreeTokenLine(&TokenList, &TokenCount); SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -1148,6 +1195,7 @@ MyFreePool(SubmenuName); MyFreePool(InitrdName); MyFreePool(File); + MyFreePool(KernelVersion); } // if } // static VOID AddKernelToSubmenu() @@ -1187,7 +1235,8 @@ } else { if (StriSubCmp(L"vmlinuz-0-rescue", NewEntry->FileName)) LinuxRescue = TRUE; - while ((CurrentEntry != NULL) && (LinuxRescue || (TimeComp(&(NewEntry->TimeStamp), &(CurrentEntry->TimeStamp)) < 0))) { + while ((CurrentEntry != NULL) && !StriSubCmp(L"vmlinuz-0-rescue", CurrentEntry->FileName) && + (LinuxRescue || (TimeComp(&(NewEntry->TimeStamp), &(CurrentEntry->TimeStamp)) < 0))) { PrevEntry = CurrentEntry; CurrentEntry = CurrentEntry->NextEntry; } // while @@ -1219,12 +1268,18 @@ // Returns TRUE if none of these conditions is met -- that is, if the path is // eligible for scanning. static BOOLEAN ShouldScan(REFIT_VOLUME *Volume, CHAR16 *Path) { - CHAR16 *VolName = NULL, *DontScanDir, *PathCopy = NULL; + CHAR16 *VolName = NULL, *DontScanDir, *PathCopy = NULL, *VolGuid = NULL; UINTN i = 0; BOOLEAN ScanIt = TRUE; - if ((IsIn(Volume->VolName, GlobalConfig.DontScanVolumes)) || (IsIn(Volume->PartName, GlobalConfig.DontScanVolumes))) + VolGuid = GuidAsString(&(Volume->PartGuid)); + if ((IsIn(Volume->VolName, GlobalConfig.DontScanVolumes)) || (IsIn(Volume->PartName, GlobalConfig.DontScanVolumes)) || + (IsIn(VolGuid, GlobalConfig.DontScanVolumes))) { + MyFreePool(VolGuid); return FALSE; + } else { + MyFreePool(VolGuid); + } // if/else if (MyStriCmp(Path, SelfDirPath) && (Volume->DeviceHandle == SelfVolume->DeviceHandle)) return FALSE; @@ -1232,7 +1287,6 @@ // See if Path includes an explicit volume declaration that's NOT Volume.... PathCopy = StrDuplicate(Path); if (SplitVolumeAndFilename(&PathCopy, &VolName)) { - VolumeNumberToName(Volume, &VolName); if (VolName && !MyStriCmp(VolName, Volume->VolName)) { ScanIt = FALSE; } // if @@ -1245,9 +1299,8 @@ while (ScanIt && (DontScanDir = FindCommaDelimited(GlobalConfig.DontScanDirs, i++))) { SplitVolumeAndFilename(&DontScanDir, &VolName); CleanUpPathNameSlashes(DontScanDir); - VolumeNumberToName(Volume, &VolName); if (VolName != NULL) { - if (MyStriCmp(VolName, Volume->VolName) && MyStriCmp(DontScanDir, Path)) + if (VolumeMatchesDescription(Volume, VolName) && MyStriCmp(DontScanDir, Path)) ScanIt = FALSE; } else { if (MyStriCmp(DontScanDir, Path)) @@ -1300,9 +1353,7 @@ return FALSE; } - if (FallbackSize != FileSize) { // not same size, so can't be identical - AreIdentical = FALSE; - } else { // could be identical; do full check.... + if (FallbackSize == FileSize) { // could be identical; do full check.... FileContents = AllocatePool(FileSize); FallbackContents = AllocatePool(FallbackSize); if (FileContents && FallbackContents) { @@ -1333,25 +1384,20 @@ // file to fail to open, which would return a false positive -- but as I use // this function to exclude symbolic links from the list of boot loaders, // that would be fine, since such boot loaders wouldn't work.) -static BOOLEAN IsSymbolicLink(REFIT_VOLUME *Volume, CHAR16 *Path, EFI_FILE_INFO *DirEntry) { +// CAUTION: *FullName MUST be properly cleaned up (via CleanUpPathNameSlashes()) +static BOOLEAN IsSymbolicLink(REFIT_VOLUME *Volume, CHAR16 *FullName, EFI_FILE_INFO *DirEntry) { EFI_FILE_HANDLE FileHandle; EFI_FILE_INFO *FileInfo = NULL; EFI_STATUS Status; UINTN FileSize2 = 0; - CHAR16 *FileName; - - FileName = StrDuplicate(Path); - MergeStrings(&FileName, DirEntry->FileName, L'\\'); - CleanUpPathNameSlashes(FileName); - Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FileHandle, FullName, EFI_FILE_MODE_READ, 0); if (Status == EFI_SUCCESS) { FileInfo = LibFileInfo(FileHandle); if (FileInfo != NULL) FileSize2 = FileInfo->FileSize; } - MyFreePool(FileName); MyFreePool(FileInfo); return (DirEntry->FileSize != FileSize2); @@ -1363,15 +1409,14 @@ // there's no point in cluttering the display with two kernels that will // behave identically on non-SB systems, or when one will fail when SB // is active. -static BOOLEAN HasSignedCounterpart(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *Filename) { +// CAUTION: *FullName MUST be properly cleaned up (via CleanUpPathNameSlashes()) +static BOOLEAN HasSignedCounterpart(IN REFIT_VOLUME *Volume, IN CHAR16 *FullName) { CHAR16 *NewFile = NULL; BOOLEAN retval = FALSE; - MergeStrings(&NewFile, Path, 0); - MergeStrings(&NewFile, Filename, L'\\'); + MergeStrings(&NewFile, FullName, 0); MergeStrings(&NewFile, L".efi.signed", 0); if (NewFile != NULL) { - CleanUpPathNameSlashes(NewFile); if (FileExists(Volume->RootDir, NewFile)) retval = TRUE; MyFreePool(NewFile); @@ -1390,7 +1435,7 @@ EFI_STATUS Status; REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry; - CHAR16 FileName[256], *Extension; + CHAR16 Message[256], *Extension, *FullName; struct LOADER_LIST *LoaderList = NULL, *NewLoader; LOADER_ENTRY *FirstKernel = NULL, *LatestEntry = NULL; BOOLEAN FoundFallbackDuplicate = FALSE, IsLinux = FALSE, InSelfPath; @@ -1402,35 +1447,31 @@ DirIterOpen(Volume->RootDir, Path, &DirIter); while (DirIterNext(&DirIter, 2, Pattern, &DirEntry)) { Extension = FindExtension(DirEntry->FileName); + FullName = StrDuplicate(Path); + MergeStrings(&FullName, DirEntry->FileName, L'\\'); + CleanUpPathNameSlashes(FullName); if (DirEntry->FileName[0] == '.' || MyStriCmp(Extension, L".icns") || MyStriCmp(Extension, L".png") || (MyStriCmp(DirEntry->FileName, FALLBACK_BASENAME) && (MyStriCmp(Path, L"EFI\\BOOT"))) || FilenameIn(Volume, Path, DirEntry->FileName, SHELL_NAMES) || - IsSymbolicLink(Volume, Path, DirEntry) || /* is symbolic link */ - HasSignedCounterpart(Volume, Path, DirEntry->FileName) || /* a file with same name plus ".efi.signed" is present */ - FilenameIn(Volume, Path, DirEntry->FileName, GlobalConfig.DontScanFiles)) { + IsSymbolicLink(Volume, FullName, DirEntry) || /* is symbolic link */ + HasSignedCounterpart(Volume, FullName) || /* a file with same name plus ".efi.signed" is present */ + FilenameIn(Volume, Path, DirEntry->FileName, GlobalConfig.DontScanFiles) || + !IsValidLoader(Volume->RootDir, FullName)) { continue; // skip this } - if (Path) - SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName); - else - SPrint(FileName, 255, L"\\%s", DirEntry->FileName); - CleanUpPathNameSlashes(FileName); - - if(!IsValidLoader(Volume->RootDir, FileName)) - continue; - NewLoader = AllocateZeroPool(sizeof(struct LOADER_LIST)); if (NewLoader != NULL) { - NewLoader->FileName = StrDuplicate(FileName); + NewLoader->FileName = StrDuplicate(FullName); NewLoader->TimeStamp = DirEntry->ModificationTime; LoaderList = AddLoaderListEntry(LoaderList, NewLoader); - if (DuplicatesFallback(Volume, FileName)) + if (DuplicatesFallback(Volume, FullName)) FoundFallbackDuplicate = TRUE; } // if MyFreePool(Extension); + MyFreePool(FullName); } // while NewLoader = LoaderList; @@ -1458,10 +1499,10 @@ // it down to buggy EFI implementations and ignoring that particular error.... if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { if (Path) - SPrint(FileName, 255, L"while scanning the %s directory", Path); + SPrint(Message, 255, L"while scanning the %s directory on %s", Path, Volume->VolName); else - StrCpy(FileName, L"while scanning the root directory"); - CheckError(Status, FileName); + SPrint(Message, 255, L"while scanning the root directory on %s", Path, Volume->VolName); + CheckError(Status, Message); } // if (Status != EFI_NOT_FOUND) } // if not scanning a blacklisted directory @@ -1514,11 +1555,30 @@ } } // VOID ScanNetBoot() +// Adds *FullFileName as a macOS loader, if it exists. +// Returns TRUE if the fallback loader is NOT a duplicate of this one, +// FALSE if it IS a duplicate. +static BOOLEAN ScanMacOsLoader(REFIT_VOLUME *Volume, CHAR16* FullFileName) { + BOOLEAN ScanFallbackLoader = TRUE; + CHAR16 *VolName = NULL, *PathName = NULL, *FileName = NULL; + + SplitPathName(FullFileName, &VolName, &PathName, &FileName); + if (FileExists(Volume->RootDir, FullFileName) && !FilenameIn(Volume, PathName, L"boot.efi", GlobalConfig.DontScanFiles)) { + AddLoaderEntry(FullFileName, L"macOS", Volume, TRUE); + if (DuplicatesFallback(Volume, FullFileName)) + ScanFallbackLoader = FALSE; + } // if + MyFreePool(VolName); + MyFreePool(PathName); + MyFreePool(FileName); + return ScanFallbackLoader; +} // VOID ScanMacOsLoader() + static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { EFI_STATUS Status; REFIT_DIR_ITER EfiDirIter; EFI_FILE_INFO *EfiDirEntry; - CHAR16 FileName[256], *Directory = NULL, *MatchPatterns, *VolName = NULL, *SelfPath; + CHAR16 FileName[256], *Directory = NULL, *MatchPatterns, *VolName = NULL, *SelfPath, *Temp; UINTN i, Length; BOOLEAN ScanFallbackLoader = TRUE; BOOLEAN FoundBRBackup = FALSE; @@ -1528,14 +1588,21 @@ if (GlobalConfig.ScanAllLinux) MergeStrings(&MatchPatterns, LINUX_MATCH_PATTERNS, L','); - // check for Mac OS X boot loader + // check for macOS boot loader if (ShouldScan(Volume, MACOSX_LOADER_DIR)) { StrCpy(FileName, MACOSX_LOADER_PATH); - if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, MACOSX_LOADER_DIR, L"boot.efi", GlobalConfig.DontScanFiles)) { - AddLoaderEntry(FileName, L"Mac OS X", Volume, TRUE); - if (DuplicatesFallback(Volume, FileName)) - ScanFallbackLoader = FALSE; - } + ScanFallbackLoader &= ScanMacOsLoader(Volume, FileName); + DirIterOpen(Volume->RootDir, L"\\", &EfiDirIter); + while (DirIterNext(&EfiDirIter, 1, NULL, &EfiDirEntry)) { + if (IsGuid(EfiDirEntry->FileName)) { + SPrint(FileName, 255, L"%s\\%s", EfiDirEntry->FileName, MACOSX_LOADER_PATH); + ScanFallbackLoader &= ScanMacOsLoader(Volume, FileName); + SPrint(FileName, 255, L"%s\\%s", EfiDirEntry->FileName, L"boot.efi"); + if (!StriSubCmp(FileName, GlobalConfig.MacOSRecoveryFiles)) + MergeStrings(&GlobalConfig.MacOSRecoveryFiles, FileName, L','); + } // if + } // while + Status = DirIterClose(&EfiDirIter); // check for XOM StrCpy(FileName, L"System\\Library\\CoreServices\\xom.efi"); @@ -1582,8 +1649,11 @@ ScanFallbackLoader = FALSE; } // while() Status = DirIterClose(&EfiDirIter); - if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) - CheckError(Status, L"while scanning the EFI directory"); + if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { + Temp = PoolPrint(L"while scanning the EFI directory on %s", Volume->VolName); + CheckError(Status, Temp); + MyFreePool(Temp); + } // if // Scan user-specified (or additional default) directories.... i = 0; @@ -1607,8 +1677,9 @@ // If not a duplicate & if it exists & if it's not us, create an entry // for the fallback boot loader - if (ScanFallbackLoader && FileExists(Volume->RootDir, FALLBACK_FULLNAME) && ShouldScan(Volume, L"EFI\\BOOT")) { - AddLoaderEntry(FALLBACK_FULLNAME, L"Fallback boot loader", Volume, TRUE); + if (ScanFallbackLoader && FileExists(Volume->RootDir, FALLBACK_FULLNAME) && ShouldScan(Volume, L"EFI\\BOOT") && + !FilenameIn(Volume, L"EFI\\BOOT", FALLBACK_BASENAME, GlobalConfig.DontScanFiles)) { + AddLoaderEntry(FALLBACK_FULLNAME, L"Fallback boot loader", Volume, TRUE); } } // if } // static VOID ScanEfiFiles() @@ -1672,12 +1743,12 @@ { BeginExternalScreen(Entry->UseGraphicsMode, Entry->me.Title + 6); // assumes "Start " as assigned below StoreLoaderName(Entry->me.Title); - StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI, - Basename(Entry->LoaderPath), Entry->OSType, NULL, TRUE, FALSE); + StartEFIImage(Entry->Volume, Entry->LoaderPath, Entry->LoadOptions, + Basename(Entry->LoaderPath), Entry->OSType, TRUE, FALSE); FinishExternalScreen(); } /* static VOID StartTool() */ -static LOADER_ENTRY * AddToolEntry(EFI_HANDLE DeviceHandle, IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN EG_IMAGE *Image, +static LOADER_ENTRY * AddToolEntry(REFIT_VOLUME *Volume, IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN EG_IMAGE *Image, IN CHAR16 ShortcutLetter, IN BOOLEAN UseGraphicsMode) { LOADER_ENTRY *Entry; @@ -1692,7 +1763,7 @@ Entry->me.ShortcutLetter = ShortcutLetter; Entry->me.Image = Image; Entry->LoaderPath = (LoaderPath) ? StrDuplicate(LoaderPath) : NULL; - Entry->DevicePath = FileDevicePath(DeviceHandle, Entry->LoaderPath); + Entry->Volume = Volume; Entry->UseGraphicsMode = UseGraphicsMode; AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); @@ -1700,10 +1771,15 @@ } /* static LOADER_ENTRY * AddToolEntry() */ // Locates boot loaders. NOTE: This assumes that GlobalConfig.LegacyType is set correctly. -static VOID ScanForBootloaders(VOID) { +static VOID ScanForBootloaders(BOOLEAN ShowMessage) { UINTN i; CHAR8 s; BOOLEAN ScanForLegacy = FALSE; + EG_PIXEL BGColor = COLOR_LIGHTBLUE; + CHAR16 *HiddenTags; + + if (ShowMessage) + egDisplayMessage(L"Scanning for boot loaders; please wait....", &BGColor, CENTER); // Determine up-front if we'll be scanning for legacy loaders.... for (i = 0; i < NUM_SCAN_OPTIONS; i++) { @@ -1718,6 +1794,16 @@ BdsAddNonExistingLegacyBootOptions(); } // if + HiddenTags = ReadHiddenTags(L"HiddenTags"); + if ((HiddenTags) && (StrLen(HiddenTags) > 0)) { + MergeStrings(&GlobalConfig.DontScanFiles, HiddenTags, L','); + } + HiddenTags = ReadHiddenTags(L"HiddenLegacy"); + if ((HiddenTags) && (StrLen(HiddenTags) > 0)) { + MergeStrings(&GlobalConfig.DontScanVolumes, HiddenTags, L','); + } + MyFreePool(HiddenTags); + // scan for loaders and tools, add them to the menu for (i = 0; i < NUM_SCAN_OPTIONS; i++) { switch(GlobalConfig.ScanFor[i]) { @@ -1756,6 +1842,32 @@ FinishTextScreen(FALSE); } // static VOID ScanForBootloaders() +// Checks to see if a specified file seems to be a valid tool. +// Returns TRUE if it passes all tests, FALSE otherwise +static BOOLEAN IsValidTool(IN REFIT_VOLUME *BaseVolume, CHAR16 *PathName) { + CHAR16 *DontVolName = NULL, *DontPathName = NULL, *DontFileName = NULL, *DontScanThis; + CHAR16 *TestVolName = NULL, *TestPathName = NULL, *TestFileName = NULL; + BOOLEAN retval = TRUE; + UINTN i = 0; + + if (FileExists(BaseVolume->RootDir, PathName) && IsValidLoader(BaseVolume->RootDir, PathName)) { + SplitPathName(PathName, &TestVolName, &TestPathName, &TestFileName); + while (retval && (DontScanThis = FindCommaDelimited(GlobalConfig.DontScanTools, i++))) { + SplitPathName(DontScanThis, &DontVolName, &DontPathName, &DontFileName); + if (MyStriCmp(TestFileName, DontFileName) && + ((DontPathName == NULL) || (MyStriCmp(TestPathName, DontPathName))) && + ((DontVolName == NULL) || (VolumeMatchesDescription(BaseVolume, DontVolName)))) { + retval = FALSE; + } // if + } // while + } else + retval = FALSE; + MyFreePool(TestVolName); + MyFreePool(TestPathName); + MyFreePool(TestFileName); + return retval; +} // VOID IsValidTool() + // Locate a single tool from the specified Locations using one of the // specified Names and add it to the menu. static VOID FindTool(CHAR16 *Locations, CHAR16 *Names, CHAR16 *Description, UINTN Icon) { @@ -1768,11 +1880,9 @@ PathName = StrDuplicate(DirName); MergeStrings(&PathName, FileName, MyStriCmp(PathName, L"\\") ? 0 : L'\\'); for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { - if ((Volumes[VolumeIndex]->RootDir != NULL) && - (FileExists(Volumes[VolumeIndex]->RootDir, PathName)) && - IsValidLoader(Volumes[VolumeIndex]->RootDir, PathName)) { - SPrint(FullDescription, 255, L"%s at %s on %s", Description, PathName, Volumes[VolumeIndex]->VolName); - AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, PathName, FullDescription, BuiltinIcon(Icon), 'S', FALSE); + if ((Volumes[VolumeIndex]->RootDir != NULL) && (IsValidTool(Volumes[VolumeIndex], PathName))) { + SPrint(FullDescription, 255, L"%s at %s on %s", Description, PathName, Volumes[VolumeIndex]->VolName); + AddToolEntry(Volumes[VolumeIndex], PathName, FullDescription, BuiltinIcon(Icon), 'S', FALSE); } // if } // for MyFreePool(PathName); @@ -1785,7 +1895,7 @@ // Add the second-row tags containing built-in and external tools (EFI shell, // reboot, etc.) static VOID ScanForTools(VOID) { - CHAR16 *FileName = NULL, *VolName = NULL, *MokLocations, Description[256]; + CHAR16 *FileName = NULL, *VolName = NULL, *MokLocations, Description[256], *HiddenTools; REFIT_MENU_ENTRY *TempMenuEntry; UINTN i, j, VolumeIndex; UINT64 osind; @@ -1796,6 +1906,12 @@ if (MokLocations != NULL) MergeStrings(&MokLocations, SelfDirPath, L','); + HiddenTools = ReadHiddenTags(L"HiddenTools"); + if ((HiddenTools) && (StrLen(HiddenTools) > 0)) { + MergeStrings(&GlobalConfig.DontScanTools, HiddenTools, L','); + } + MyFreePool(HiddenTools); + for (i = 0; i < NUM_TOOLS; i++) { switch(GlobalConfig.ShowTools[i]) { // NOTE: Be sure that FileName is NULL at the end of each case. @@ -1823,6 +1939,14 @@ AddMenuEntry(&MainMenu, TempMenuEntry); break; + case TAG_HIDDEN: + if (GlobalConfig.HiddenTags) { + TempMenuEntry = CopyMenuEntry(&MenuEntryManageHidden); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_HIDDEN); + AddMenuEntry(&MainMenu, TempMenuEntry); + } + break; + case TAG_FIRMWARE: if (EfivarGetRaw(&GlobalGuid, L"OsIndicationsSupported", &b, &j) == EFI_SUCCESS) { osind = (UINT64)*b; @@ -1837,8 +1961,8 @@ case TAG_SHELL: j = 0; while ((FileName = FindCommaDelimited(SHELL_NAMES, j++)) != NULL) { - if (FileExists(SelfRootDir, FileName) && IsValidLoader(SelfRootDir, FileName)) { - AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), + if (IsValidTool(SelfVolume, FileName)) { + AddToolEntry(SelfVolume, FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), 'S', FALSE); } MyFreePool(FileName); @@ -1848,7 +1972,7 @@ case TAG_GPTSYNC: j = 0; while ((FileName = FindCommaDelimited(GPTSYNC_NAMES, j++)) != NULL) { - if (FileExists(SelfRootDir, FileName) && IsValidLoader(SelfRootDir, FileName)) { + if (IsValidTool(SelfVolume, FileName)) { AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"Hybrid MBR tool", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'P', FALSE); } // if @@ -1860,8 +1984,8 @@ case TAG_GDISK: j = 0; while ((FileName = FindCommaDelimited(GDISK_NAMES, j++)) != NULL) { - if (FileExists(SelfRootDir, FileName) && IsValidLoader(SelfRootDir, FileName)) { - AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"disk partitioning tool", + if (IsValidTool(SelfVolume, FileName)) { + AddToolEntry(SelfVolume, FileName, L"disk partitioning tool", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'G', FALSE); } // if MyFreePool(FileName); @@ -1872,8 +1996,8 @@ case TAG_NETBOOT: j = 0; while ((FileName = FindCommaDelimited(NETBOOT_NAMES, j++)) != NULL) { - if (FileExists(SelfRootDir, FileName) && IsValidLoader(SelfRootDir, FileName)) { - AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"Netboot", + if (IsValidTool(SelfVolume, FileName)) { + AddToolEntry(SelfVolume, FileName, L"Netboot", BuiltinIcon(BUILTIN_ICON_TOOL_NETBOOT), 'N', FALSE); } // if MyFreePool(FileName); @@ -1882,18 +2006,18 @@ break; case TAG_APPLE_RECOVERY: - FileName = StrDuplicate(L"\\com.apple.recovery.boot\\boot.efi"); for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { - if ((Volumes[VolumeIndex]->RootDir != NULL) && - (FileExists(Volumes[VolumeIndex]->RootDir, FileName)) && - IsValidLoader(Volumes[VolumeIndex]->RootDir, FileName)) { - SPrint(Description, 255, L"Apple Recovery on %s", Volumes[VolumeIndex]->VolName); - AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, FileName, Description, - BuiltinIcon(BUILTIN_ICON_TOOL_APPLE_RESCUE), 'R', TRUE); - } // if + j = 0; + while ((FileName = FindCommaDelimited(GlobalConfig.MacOSRecoveryFiles, j++)) != NULL) { + if ((Volumes[VolumeIndex]->RootDir != NULL)) { + if ((IsValidTool(Volumes[VolumeIndex], FileName))) { + SPrint(Description, 255, L"Apple Recovery on %s", Volumes[VolumeIndex]->VolName); + AddToolEntry(Volumes[VolumeIndex], FileName, Description, + BuiltinIcon(BUILTIN_ICON_TOOL_APPLE_RESCUE), 'R', TRUE); + } // if + } // if + } // while } // for - MyFreePool(FileName); - FileName = NULL; break; case TAG_WINDOWS_RECOVERY: @@ -1902,11 +2026,10 @@ SplitVolumeAndFilename(&FileName, &VolName); for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { if ((Volumes[VolumeIndex]->RootDir != NULL) && - (FileExists(Volumes[VolumeIndex]->RootDir, FileName)) && - IsValidLoader(Volumes[VolumeIndex]->RootDir, FileName) && + (IsValidTool(Volumes[VolumeIndex], FileName)) && ((VolName == NULL) || MyStriCmp(VolName, Volumes[VolumeIndex]->VolName))) { SPrint(Description, 255, L"Microsoft Recovery on %s", Volumes[VolumeIndex]->VolName); - AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, FileName, Description, + AddToolEntry(Volumes[VolumeIndex], FileName, Description, BuiltinIcon(BUILTIN_ICON_TOOL_WINDOWS_RESCUE), 'R', TRUE); } // if } // for @@ -1942,15 +2065,7 @@ } // static VOID ScanForTools // Rescan for boot loaders -static VOID RescanAll(BOOLEAN DisplayMessage) { - EG_PIXEL BGColor; - - BGColor.b = 255; - BGColor.g = 175; - BGColor.r = 100; - BGColor.a = 0; - if (DisplayMessage) - egDisplayMessage(L"Scanning for new boot loaders; please wait....", &BGColor); +VOID RescanAll(BOOLEAN DisplayMessage) { FreeList((VOID ***) &(MainMenu.Entries), &MainMenu.EntryCount); MainMenu.Entries = NULL; MainMenu.EntryCount = 0; @@ -1958,9 +2073,8 @@ ScanVolumes(); ReadConfig(GlobalConfig.ConfigFilename); SetVolumeIcons(); - ScanForBootloaders(); + ScanForBootloaders(TRUE); ScanForTools(); - SetupScreen(); } // VOID RescanAll() #ifdef __MAKEWITH_TIANO @@ -2056,7 +2170,7 @@ REFIT_MENU_ENTRY *ChosenEntry; UINTN MenuExit, i; CHAR16 *SelectionName = NULL; - EG_PIXEL BGColor; + EG_PIXEL BGColor = COLOR_LIGHTBLUE; // bootstrap InitializeLib(ImageHandle, SystemTable); @@ -2071,10 +2185,16 @@ CopyMem(GlobalConfig.ScanFor, "ihebocm ", NUM_SCAN_OPTIONS); SetConfigFilename(ImageHandle); MokProtocol = SecureBootSetup(); - LoadDrivers(); - ScanVolumes(); // Do before ReadConfig() because it needs SelfVolume->VolName + + // Scan volumes first to find SelfVolume, which is required by LoadDrivers(); + // however, if drivers are loaded, a second call to ScanVolumes() is needed + // to register the new filesystem(s) accessed by the drivers. + // Also, ScanVolumes() must be done before ReadConfig(), which needs + // SelfVolume->VolName. + ScanVolumes(); + if (LoadDrivers()) + ScanVolumes(); ReadConfig(GlobalConfig.ConfigFilename); - SetVolumeIcons(); if (GlobalConfig.SpoofOSXVersion && GlobalConfig.SpoofOSXVersion[0] != L'\0') SetAppleOSInfo(); @@ -2087,19 +2207,21 @@ refit_call4_wrapper(BS->SetWatchdogTimer, 0x0000, 0x0000, 0x0000, NULL); // further bootstrap (now with config available) - ScanForBootloaders(); - ScanForTools(); SetupScreen(); + SetVolumeIcons(); + ScanForBootloaders(GlobalConfig.ScanDelay == 0); + ScanForTools(); + // SetupScreen() clears the screen; but ScanForBootloaders() may display a + // message that must be deleted, so do so + BltClearScreen(TRUE); + pdInitialize(); if (GlobalConfig.ScanDelay > 0) { - BGColor.b = 255; - BGColor.g = 175; - BGColor.r = 100; - BGColor.a = 0; if (GlobalConfig.ScanDelay > 1) - egDisplayMessage(L"Pausing before disk scan; please wait....", &BGColor); + egDisplayMessage(L"Pausing before disk scan; please wait....", &BGColor, CENTER); for (i = 0; i < GlobalConfig.ScanDelay; i++) refit_call1_wrapper(BS->Stall, 1000000); + BltClearScreen(TRUE); RescanAll(GlobalConfig.ScanDelay > 1); } // if @@ -2150,6 +2272,10 @@ StartTool((LOADER_ENTRY *)ChosenEntry); break; + case TAG_HIDDEN: // Manage hidden tag entries + ManageHiddenTags(); + break; + case TAG_EXIT: // Terminate rEFInd if ((MokProtocol) && !SecureBootUninstall()) { MainLoopRunning = FALSE; // just in case we get this far diff -Nru refind-0.10.4/refind/main.c.orig refind-0.11.2/refind/main.c.orig --- refind-0.10.4/refind/main.c.orig 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/refind/main.c.orig 2017-08-04 13:15:24.000000000 +0000 @@ -0,0 +1,2315 @@ +/* + * refind/main.c + * Main code for the boot menu + * + * Copyright (c) 2006-2010 Christoph Pfisterer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Christoph Pfisterer nor the names of the + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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-2017 Roderick W. Smith + * + * Modifications distributed under the terms of the GNU General Public + * License (GPL) version 3 (GPLv3), or (at your option) any later version. + * + */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "global.h" +#include "config.h" +#include "screen.h" +#include "legacy.h" +#include "lib.h" +#include "icns.h" +#include "menu.h" +#include "pointer.h" +#include "mok.h" +#include "gpt.h" +#include "apple.h" +#include "mystrings.h" +#include "security_policy.h" +#include "driver_support.h" +#include "../include/Handle.h" +#include "../include/refit_call_wrapper.h" +#include "../include/version.h" +#include "../EfiLib/BdsHelper.h" +#include "../EfiLib/legacy.h" + +#ifdef __MAKEWITH_GNUEFI +#ifndef EFI_SECURITY_VIOLATION +#define EFI_SECURITY_VIOLATION EFIERR (26) +#endif +#endif + +#ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL +#endif + +#ifdef __MAKEWITH_TIANO +#define LibLocateHandle gBS->LocateHandleBuffer +#endif + +// +// constants + +#define MACOSX_LOADER_DIR L"System\\Library\\CoreServices" +#define MACOSX_LOADER_PATH ( MACOSX_LOADER_DIR L"\\boot.efi" ) +#if defined (EFIX64) +#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellx64.efi,\\shell.efi,\\shellx64.efi" +#define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi,\\EFI\\tools\\gptsync_x64.efi" +#define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_x64.efi" +#define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi" +#define MEMTEST_NAMES L"memtest86.efi,memtest86_x64.efi,memtest86x64.efi,bootx64.efi" +#define FALLBACK_FULLNAME L"EFI\\BOOT\\bootx64.efi" +#define FALLBACK_BASENAME L"bootx64.efi" +#define EFI_STUB_ARCH 0x8664 +EFI_GUID gFreedesktopRootGuid = { 0x4f68bce3, 0xe8cd, 0x4db1, { 0x96, 0xe7, 0xfb, 0xca, 0xf9, 0x84, 0xb7, 0x09 }}; +#elif defined (EFI32) +#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellia32.efi,\\shell.efi,\\shellia32.efi" +#define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi,\\EFI\\tools\\gptsync_ia32.efi" +#define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_ia32.efi" +#define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi" +#define MEMTEST_NAMES L"memtest86.efi,memtest86_ia32.efi,memtest86ia32.efi,bootia32.efi" +#define FALLBACK_FULLNAME L"EFI\\BOOT\\bootia32.efi" +#define FALLBACK_BASENAME L"bootia32.efi" +#define EFI_STUB_ARCH 0x014c +EFI_GUID gFreedesktopRootGuid = { 0x44479540, 0xf297, 0x41b2, { 0x9a, 0xf7, 0xd1, 0x31, 0xd5, 0xf0, 0x45, 0x8a }}; +#elif defined (EFIAARCH64) +#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellaa64.efi,\\shell.efi,\\shellaa64.efi" +#define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi,\\EFI\\tools\\gptsync_aa64.efi" +#define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_aa64.efi" +#define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi" +#define MEMTEST_NAMES L"memtest86.efi,memtest86_aa64.efi,memtest86aa64.efi,bootaa64.efi" +#define FALLBACK_FULLNAME L"EFI\\BOOT\\bootaa64.efi" +#define FALLBACK_BASENAME L"bootaa64.efi" +#define EFI_STUB_ARCH 0xaa64 +EFI_GUID gFreedesktopRootGuid = { 0xb921b045, 0x1df0, 0x41c3, { 0xaf, 0x44, 0x4c, 0x6f, 0x28, 0x0d, 0x3f, 0xae }}; +#else +#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\shell.efi" +#define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi" +#define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi" +#define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi" +#define MEMTEST_NAMES L"memtest86.efi" +#define DRIVER_DIRS L"drivers" +#define FALLBACK_FULLNAME L"EFI\\BOOT\\boot.efi" /* Not really correct */ +#define FALLBACK_BASENAME L"boot.efi" /* Not really correct */ +// Below is GUID for ARM32 +EFI_GUID gFreedesktopRootGuid = { 0x69dad710, 0x2ce4, 0x4e3c, { 0xb1, 0x6c, 0x21, 0xa1, 0xd4, 0x9a, 0xbe, 0xd3 }}; +#endif +#define FAT_ARCH 0x0ef1fab9 /* ID for Apple "fat" binary */ + +#define IPXE_DISCOVER_NAME L"\\efi\\tools\\ipxe_discover.efi" +#define IPXE_NAME L"\\efi\\tools\\ipxe.efi" + +// Patterns that identify Linux kernels. Added to the loader match pattern when the +// scan_all_linux_kernels option is set in the configuration file. Causes kernels WITHOUT +// a ".efi" extension to be found when scanning for boot loaders. +#define LINUX_MATCH_PATTERNS L"vmlinuz*,bzImage*,kernel*" + +// Maximum length of a text string in certain menus +#define MAX_LINE_LENGTH 65 + +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 }; +REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryExit = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryManageHidden = { L"Manage Hidden Tags Menu", TAG_HIDDEN, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryFirmware = { L"Reboot to Computer Setup Utility", TAG_FIRMWARE, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryRotateCsr = { L"Change SIP Policy", TAG_CSR_ROTATE, 1, 0, 0, NULL, NULL, NULL }; + +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, Tab, or F2 for more options; Esc or Backspace 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"" }; + +<<<<<<< HEAD +REFIT_CONFIG GlobalConfig = { /* TextOnly = */ FALSE, + /* ScanAllLinux = */ TRUE, + /* DeepLegacyScan = */ FALSE, + /* EnableAndLockVMX = */ FALSE, + /* FoldLinuxKernels = */ TRUE, + /* EnableTouch = */ FALSE, + /* HiddenTags = */ TRUE, + /* RequestedScreenWidth = */ 0, + /* RequestedScreenHeight = */ 0, + /* BannerBottomEdge = */ 0, + /* RequestedTextMode = */ DONT_CHANGE_TEXT_MODE, + /* Timeout = */ 20, + /* HideUIFlags = */ 0, + /* MaxTags = */ 0, + /* GraphicsFor = */ GRAPHICS_FOR_OSX, + /* LegacyType = */ LEGACY_TYPE_MAC, + /* ScanDelay = */ 0, + /* ScreensaverTime = */ 0, + /* IconSizes = */ { DEFAULT_BIG_ICON_SIZE / 4, DEFAULT_SMALL_ICON_SIZE, DEFAULT_BIG_ICON_SIZE }, + /* BannerScale = */ BANNER_NOSCALE, + /* *DiscoveredRoot = */ NULL, + /* *SelfDevicePath = */ NULL, + /* *BannerFileName = */ NULL, + /* *ScreenBackground = */ NULL, + /* *ConfigFilename = */ CONFIG_FILE_NAME, + /* *SelectionSmallFileName = */ NULL, + /* *SelectionBigFileName = */ NULL, + /* *DefaultSelection = */ NULL, + /* *AlsoScan = */ NULL, + /* *DontScanVolumes = */ NULL, + /* *DontScanDirs = */ NULL, + /* *DontScanFiles = */ NULL, + /* *DontScanTools = */ NULL, + /* *WindowsRecoveryFiles = */ NULL, + /* *DriverDirs = */ NULL, + /* *IconsDir = */ NULL, + /* *ExtraKernelVersionStrings = */ NULL, + /* *SpoofOSXVersion = */ NULL, + /* CsrValues = */ NULL, + /* ShowTools = */ { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY, + TAG_MOK_TOOL, TAG_ABOUT, TAG_HIDDEN, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, + TAG_FWUPDATE_TOOL, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +======= +REFIT_CONFIG GlobalConfig = { FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, + 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, + 0, 0, { DEFAULT_BIG_ICON_SIZE / 4, DEFAULT_SMALL_ICON_SIZE, DEFAULT_BIG_ICON_SIZE, DEFAULT_MOUSE_SIZE }, + BANNER_NOSCALE, 1, NULL, NULL, NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY, + TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, TAG_FWUPDATE_TOOL, + 0, 0, 0, 0, 0, 0, 0, 0 } +>>>>>>> d63734581c19715b3dc13ab89c520def8d5c4566 + }; + +EFI_GUID GlobalGuid = EFI_GLOBAL_VARIABLE; +EFI_GUID RefindGuid = REFIND_GUID_VALUE; + +GPT_DATA *gPartitions = NULL; + +// Structure used to hold boot loader filenames and time stamps in +// a linked list; used to sort entries within a directory. +struct LOADER_LIST { + CHAR16 *FileName; + EFI_TIME TimeStamp; + struct LOADER_LIST *NextEntry; +}; + +// +// misc functions +// + +static VOID AboutrEFInd(VOID) +{ + CHAR16 *FirmwareVendor; + UINT32 CsrStatus; + + if (AboutMenu.EntryCount == 0) { + AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); + AddMenuInfoLine(&AboutMenu, PoolPrint(L"rEFInd Version %s", REFIND_VERSION)); + AddMenuInfoLine(&AboutMenu, L""); + AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); + AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2017 Roderick W. Smith"); + AddMenuInfoLine(&AboutMenu, L"Portions Copyright (c) Intel Corporation and others"); + AddMenuInfoLine(&AboutMenu, L"Distributed under the terms of the GNU GPLv3 license"); + AddMenuInfoLine(&AboutMenu, L""); + AddMenuInfoLine(&AboutMenu, L"Running on:"); + AddMenuInfoLine(&AboutMenu, PoolPrint(L" EFI Revision %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & ((1 << 16) - 1))); +#if defined(EFI32) + AddMenuInfoLine(&AboutMenu, PoolPrint(L" Platform: x86 (32 bit); Secure Boot %s", + secure_mode() ? L"active" : L"inactive")); +#elif defined(EFIX64) + AddMenuInfoLine(&AboutMenu, PoolPrint(L" Platform: x86_64 (64 bit); Secure Boot %s", + secure_mode() ? L"active" : L"inactive")); +#elif defined(EFIAARCH64) + AddMenuInfoLine(&AboutMenu, PoolPrint(L" Platform: ARM (64 bit); Secure Boot %s", + secure_mode() ? L"active" : L"inactive")); +#else + AddMenuInfoLine(&AboutMenu, L" Platform: unknown"); +#endif + if (GetCsrStatus(&CsrStatus) == EFI_SUCCESS) { + RecordgCsrStatus(CsrStatus, FALSE); + AddMenuInfoLine(&AboutMenu, gCsrStatus); + } + FirmwareVendor = StrDuplicate(ST->FirmwareVendor); + LimitStringLength(FirmwareVendor, MAX_LINE_LENGTH); // More than ~65 causes empty info page on 800x600 display + AddMenuInfoLine(&AboutMenu, PoolPrint(L" Firmware: %s %d.%02d", FirmwareVendor, ST->FirmwareRevision >> 16, + ST->FirmwareRevision & ((1 << 16) - 1))); + AddMenuInfoLine(&AboutMenu, PoolPrint(L" Screen Output: %s", egScreenDescription())); + AddMenuInfoLine(&AboutMenu, L""); +#if defined(__MAKEWITH_GNUEFI) + AddMenuInfoLine(&AboutMenu, L"Built with GNU-EFI"); +#else + AddMenuInfoLine(&AboutMenu, L"Built with TianoCore EDK2"); +#endif + AddMenuInfoLine(&AboutMenu, L""); + AddMenuInfoLine(&AboutMenu, L"For more information, see the rEFInd Web site:"); + AddMenuInfoLine(&AboutMenu, L"http://www.rodsbooks.com/refind/"); + AddMenuEntry(&AboutMenu, &MenuEntryReturn); + } + + RunMenu(&AboutMenu, NULL); +} /* VOID AboutrEFInd() */ + +static VOID WarnSecureBootError(CHAR16 *Name, BOOLEAN Verbose) { + if (Name == NULL) + Name = L"the loader"; + + refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR); + Print(L"Secure Boot validation failure loading %s!\n", Name); + refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); + if (Verbose && secure_mode()) { + Print(L"\nThis computer is configured with Secure Boot active, but\n%s has failed validation.\n", Name); + Print(L"\nYou can:\n * Launch another boot loader\n"); + Print(L" * Disable Secure Boot in your firmware\n"); + Print(L" * Sign %s with a machine owner key (MOK)\n", Name); + Print(L" * Use a MOK utility (often present on the second row) to add a MOK with which\n"); + Print(L" %s has already been signed.\n", Name); + Print(L" * Use a MOK utility to register %s (\"enroll its hash\") without\n", Name); + Print(L" signing it.\n"); + Print(L"\nSee http://www.rodsbooks.com/refind/secureboot.html for more information\n"); + PauseForKey(); + } // if +} // VOID WarnSecureBootError() + +// Returns TRUE if this file is a valid EFI loader file, and is proper ARCH +static BOOLEAN IsValidLoader(EFI_FILE *RootDir, CHAR16 *FileName) { + BOOLEAN IsValid = TRUE; +#if defined (EFIX64) | defined (EFI32) | defined (EFIAARCH64) + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + CHAR8 Header[512]; + UINTN Size = sizeof(Header); + + if ((RootDir == NULL) || (FileName == NULL)) { + // Assume valid here, because Macs produce NULL RootDir (& maybe FileName) + // when launching from a Firewire drive. This should be handled better, but + // fix would have to be in StartEFIImageList() and/or in FindVolumeAndFilename(). + return TRUE; + } // if + + Status = refit_call5_wrapper(RootDir->Open, RootDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) + return FALSE; + + Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &Size, Header); + refit_call1_wrapper(FileHandle->Close, FileHandle); + + IsValid = !EFI_ERROR(Status) && + Size == sizeof(Header) && + ((Header[0] == 'M' && Header[1] == 'Z' && + (Size = *(UINT32 *)&Header[0x3c]) < 0x180 && + Header[Size] == 'P' && Header[Size+1] == 'E' && + Header[Size+2] == 0 && Header[Size+3] == 0 && + *(UINT16 *)&Header[Size+4] == EFI_STUB_ARCH) || + (*(UINT32 *)&Header == FAT_ARCH)); +#endif + return IsValid; +} // BOOLEAN IsValidLoader() + +// Launch an EFI binary. +EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, + IN CHAR16 *LoadOptions, IN UINTN LoaderType, + IN CHAR16 *ImageTitle, IN CHAR8 OSType, + OUT UINTN *ErrorInStep, + IN BOOLEAN Verbose, + IN BOOLEAN IsDriver) +{ + EFI_STATUS Status, ReturnStatus; + EFI_HANDLE ChildImageHandle, ChildImageHandle2; + EFI_LOADED_IMAGE *ChildLoadedImage = NULL; + REFIT_VOLUME *Volume = NULL; + UINTN DevicePathIndex; + CHAR16 ErrorInfo[256]; + CHAR16 *FullLoadOptions = NULL; + CHAR16 *Filename = NULL; + CHAR16 *Temp; + + if (ErrorInStep != NULL) + *ErrorInStep = 0; + + // set load options + if (LoadOptions != NULL) { + FullLoadOptions = StrDuplicate(LoadOptions); + if ((LoaderType == TYPE_EFI) && (OSType == 'M')) { + MergeStrings(&FullLoadOptions, L" ", 0); + // NOTE: That last space is also added by the EFI shell and seems to be significant + // when passing options to Apple's boot.efi... + } // if + } // if (LoadOptions != NULL) + if (Verbose) + Print(L"Starting %s\nUsing load options '%s'\n", ImageTitle, FullLoadOptions ? FullLoadOptions : L""); + + // load the image into memory + ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty + for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) { + FindVolumeAndFilename(DevicePaths[DevicePathIndex], &Volume, &Filename); + // Some EFIs crash if attempting to load driver for invalid architecture, so + // protect for this condition; but sometimes Volume comes back NULL, so provide + // an exception. (TODO: Handle this special condition better.) + if ((LoaderType == TYPE_LEGACY) || (Volume == NULL) || IsValidLoader(Volume->RootDir, Filename)) { + if (Filename && (LoaderType != TYPE_LEGACY)) { + Temp = PoolPrint(L"\\%s %s", Filename, FullLoadOptions ? FullLoadOptions : L""); + if (Temp != NULL) { + MyFreePool(FullLoadOptions); + FullLoadOptions = Temp; + } + } // if (Filename) + + // NOTE: Below commented-out line could be more efficient if file were read ahead of + // time and passed as a pre-loaded image to LoadImage(), but it doesn't work on my + // 32-bit Mac Mini or my 64-bit Intel box when launching a Linux kernel; the + // kernel returns a "Failed to handle fs_proto" error message. + // 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 (secure_mode() && ShimLoaded()) { + // Load ourself into memory. This is a trick to work around a bug in Shim 0.8, + // which ties itself into the BS->LoadImage() and BS->StartImage() functions and + // then unregisters itself from the EFI system table when its replacement + // StartImage() function is called *IF* the previous LoadImage() was for the same + // program. The result is that rEFInd can validate only the first program it + // launches (often a filesystem driver). Loading a second program (rEFInd itself, + // here, to keep it smaller than a kernel) works around this problem. See the + // replacements.c file in Shim, and especially its start_image() function, for + // the source of the problem. + // NOTE: This doesn't check the return status or handle errors. It could + // conceivably do weird things if, say, rEFInd were on a USB drive that the + // user pulls before launching a program. + refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, GlobalConfig.SelfDevicePath, + NULL, 0, &ChildImageHandle2); + } + } else { + Print(L"Invalid loader file!\n"); + ReturnStatus = EFI_LOAD_ERROR; + } + if (ReturnStatus != EFI_NOT_FOUND) { + break; + } + } // for + if ((Status == EFI_ACCESS_DENIED) || (Status == EFI_SECURITY_VIOLATION)) { + WarnSecureBootError(ImageTitle, Verbose); + goto bailout; + } + SPrint(ErrorInfo, 255, L"while loading %s", ImageTitle); + if (CheckError(Status, ErrorInfo)) { + if (ErrorInStep != NULL) + *ErrorInStep = 1; + goto bailout; + } + + ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol, + (VOID **) &ChildLoadedImage); + if (CheckError(Status, L"while getting a LoadedImageProtocol handle")) { + if (ErrorInStep != NULL) + *ErrorInStep = 2; + goto bailout_unload; + } + ChildLoadedImage->LoadOptions = (VOID *)FullLoadOptions; + ChildLoadedImage->LoadOptionsSize = FullLoadOptions ? ((UINT32)StrLen(FullLoadOptions) + 1) * sizeof(CHAR16) : 0; + // turn control over to the image + // TODO: (optionally) re-enable the EFI watchdog timer! + + // close open file handles + UninitRefitLib(); + ReturnStatus = Status = refit_call3_wrapper(BS->StartImage, ChildImageHandle, NULL, NULL); + + // control returns here when the child image calls Exit() + SPrint(ErrorInfo, 255, L"returned from %s", ImageTitle); + if (CheckError(Status, ErrorInfo)) { + if (ErrorInStep != NULL) + *ErrorInStep = 3; + } + if (IsDriver) { + // Below should have no effect on most systems, but works + // around bug with some EFIs that prevents filesystem drivers + // from binding to partitions. + ConnectFilesystemDriver(ChildImageHandle); + } + + // re-open file handles + ReinitRefitLib(); + +bailout_unload: + // unload the image, we don't care if it works or not... + if (!IsDriver) + Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle); + +bailout: + MyFreePool(FullLoadOptions); + return ReturnStatus; +} /* EFI_STATUS StartEFIImageList() */ + +EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, + IN CHAR16 *LoadOptions, IN UINTN LoaderType, + IN CHAR16 *ImageTitle, IN CHAR8 OSType, + OUT UINTN *ErrorInStep, + IN BOOLEAN Verbose, + IN BOOLEAN IsDriver) +{ + EFI_DEVICE_PATH *DevicePaths[2]; + + DevicePaths[0] = DevicePath; + DevicePaths[1] = NULL; + return StartEFIImageList(DevicePaths, LoadOptions, LoaderType, ImageTitle, OSType, ErrorInStep, Verbose, IsDriver); +} /* static EFI_STATUS StartEFIImage() */ + +// From gummiboot: Reboot the computer into its built-in user interface +static EFI_STATUS RebootIntoFirmware(VOID) { + CHAR8 *b; + UINTN size; + UINT64 osind; + EFI_STATUS err; + + osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + + err = EfivarGetRaw(&GlobalGuid, L"OsIndications", &b, &size); + if (err == EFI_SUCCESS) + osind |= (UINT64)*b; + MyFreePool(b); + + err = EfivarSetRaw(&GlobalGuid, L"OsIndications", (CHAR8 *)&osind, sizeof(UINT64), TRUE); + if (err != EFI_SUCCESS) + return err; + + refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL); + Print(L"Error calling ResetSystem: %r", err); + PauseForKey(); + return err; +} + +// Record the value of the loader's name/description in rEFInd's "PreviousBoot" EFI variable, +// if it's different from what's already stored there. +VOID StoreLoaderName(IN CHAR16 *Name) { + EFI_STATUS Status; + CHAR16 *OldName = NULL; + UINTN Length; + + if (Name) { + Status = EfivarGetRaw(&RefindGuid, L"PreviousBoot", (CHAR8**) &OldName, &Length); + if ((Status != EFI_SUCCESS) || (StrCmp(OldName, Name) != 0)) { + EfivarSetRaw(&RefindGuid, L"PreviousBoot", (CHAR8*) Name, StrLen(Name) * 2 + 2, TRUE); + } // if + MyFreePool(OldName); + } // if +} // VOID StoreLoaderName() + +// +// EFI OS loader functions +// + +// See http://www.thomas-krenn.com/en/wiki/Activating_the_Intel_VT_Virtualization_Feature +// for information on Intel VMX features +static VOID DoEnableAndLockVMX(VOID) +{ +#if defined (EFIX64) | defined (EFI32) + UINT32 msr = 0x3a; + UINT32 low_bits = 0, high_bits = 0; + + // is VMX active ? + __asm__ volatile ("rdmsr" : "=a" (low_bits), "=d" (high_bits) : "c" (msr)); + + // enable and lock vmx if not locked + if ((low_bits & 1) == 0) { + high_bits = 0; + low_bits = 0x05; + msr = 0x3a; + __asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits)); + } +#endif +} // VOID DoEnableAndLockVMX() + +static VOID StartLoader(LOADER_ENTRY *Entry, CHAR16 *SelectionName) +{ + UINTN ErrorInStep = 0; + + if (GlobalConfig.EnableAndLockVMX) { + DoEnableAndLockVMX(); + } + + BeginExternalScreen(Entry->UseGraphicsMode, L"Booting OS"); + StoreLoaderName(SelectionName); + StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI, + Basename(Entry->LoaderPath), Entry->OSType, &ErrorInStep, !Entry->UseGraphicsMode, FALSE); + FinishExternalScreen(); +} + +// Locate an initrd or initramfs file that matches the kernel specified by LoaderPath. +// The matching file has a name that begins with "init" and includes the same version +// number string as is found in LoaderPath -- but not a longer version number string. +// For instance, if LoaderPath is \EFI\kernels\bzImage-3.3.0.efi, and if \EFI\kernels +// has a file called initramfs-3.3.0.img, this function will return the string +// '\EFI\kernels\initramfs-3.3.0.img'. If the directory ALSO contains the file +// initramfs-3.3.0-rc7.img or initramfs-13.3.0.img, those files will NOT match. +// If more than one initrd file matches the extracted version string, the one +// that matches more characters AFTER (actually, from the start of) the version +// string is used. +// If no matching init file can be found, returns NULL. +static CHAR16 * FindInitrd(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) { + CHAR16 *InitrdName = NULL, *FileName, *KernelVersion, *InitrdVersion, *Path; + CHAR16 *KernelPostNum, *InitrdPostNum; + UINTN MaxSharedChars, SharedChars; + STRING_LIST *InitrdNames = NULL, *FinalInitrdName = NULL, *CurrentInitrdName = NULL, *MaxSharedInitrd; + REFIT_DIR_ITER DirIter; + EFI_FILE_INFO *DirEntry; + + FileName = Basename(LoaderPath); + KernelVersion = FindNumbers(FileName); + Path = FindPath(LoaderPath); + + // Add trailing backslash for root directory; necessary on some systems, but must + // NOT be added to all directories, since on other systems, a trailing backslash on + // anything but the root directory causes them to flake out! + if (StrLen(Path) == 0) { + MergeStrings(&Path, L"\\", 0); + } // if + DirIterOpen(Volume->RootDir, Path, &DirIter); + // Now add a trailing backslash if it was NOT added earlier, for consistency in + // building the InitrdName later.... + if ((StrLen(Path) > 0) && (Path[StrLen(Path) - 1] != L'\\')) + MergeStrings(&Path, L"\\", 0); + while (DirIterNext(&DirIter, 2, L"init*", &DirEntry)) { + InitrdVersion = FindNumbers(DirEntry->FileName); + if (((KernelVersion != NULL) && (MyStriCmp(InitrdVersion, KernelVersion))) || + ((KernelVersion == NULL) && (InitrdVersion == NULL))) { + CurrentInitrdName = AllocateZeroPool(sizeof(STRING_LIST)); + if (InitrdNames == NULL) + InitrdNames = FinalInitrdName = CurrentInitrdName; + if (CurrentInitrdName) { + CurrentInitrdName->Value = PoolPrint(L"%s%s", Path, DirEntry->FileName); + if (CurrentInitrdName != FinalInitrdName) { + FinalInitrdName->Next = CurrentInitrdName; + FinalInitrdName = CurrentInitrdName; + } // if + } // if + } // if + MyFreePool(InitrdVersion); + } // while + if (InitrdNames) { + if (InitrdNames->Next == NULL) { + InitrdName = StrDuplicate(InitrdNames -> Value); + } else { + MaxSharedInitrd = CurrentInitrdName = InitrdNames; + MaxSharedChars = 0; + while (CurrentInitrdName != NULL) { + KernelPostNum = MyStrStr(LoaderPath, KernelVersion); + InitrdPostNum = MyStrStr(CurrentInitrdName->Value, KernelVersion); + SharedChars = NumCharsInCommon(KernelPostNum, InitrdPostNum); + if (SharedChars > MaxSharedChars) { + MaxSharedChars = SharedChars; + MaxSharedInitrd = CurrentInitrdName; + } // if + // TODO: Compute number of shared characters & compare with max. + CurrentInitrdName = CurrentInitrdName->Next; + } + if (MaxSharedInitrd) + InitrdName = StrDuplicate(MaxSharedInitrd->Value); + } // if/else + } // if + DeleteStringList(InitrdNames); + + // Note: Don't FreePool(FileName), since Basename returns a pointer WITHIN the string it's passed. + MyFreePool(KernelVersion); + MyFreePool(Path); + return (InitrdName); +} // static CHAR16 * FindInitrd() + +LOADER_ENTRY * AddPreparedLoaderEntry(LOADER_ENTRY *Entry) { + AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); + + return(Entry); +} // LOADER_ENTRY * AddPreparedLoaderEntry() + +// Creates a copy of a menu screen. +// Returns a pointer to the copy of the menu screen. +static REFIT_MENU_SCREEN* CopyMenuScreen(REFIT_MENU_SCREEN *Entry) { + REFIT_MENU_SCREEN *NewEntry; + UINTN i; + + NewEntry = AllocateZeroPool(sizeof(REFIT_MENU_SCREEN)); + if ((Entry != NULL) && (NewEntry != NULL)) { + CopyMem(NewEntry, Entry, sizeof(REFIT_MENU_SCREEN)); + NewEntry->Title = (Entry->Title) ? StrDuplicate(Entry->Title) : NULL; + NewEntry->TimeoutText = (Entry->TimeoutText) ? StrDuplicate(Entry->TimeoutText) : NULL; + if (Entry->TitleImage != NULL) { + NewEntry->TitleImage = AllocatePool(sizeof(EG_IMAGE)); + if (NewEntry->TitleImage != NULL) + CopyMem(NewEntry->TitleImage, Entry->TitleImage, sizeof(EG_IMAGE)); + } // if + NewEntry->InfoLines = (CHAR16**) AllocateZeroPool(Entry->InfoLineCount * (sizeof(CHAR16*))); + for (i = 0; i < Entry->InfoLineCount && NewEntry->InfoLines; i++) { + NewEntry->InfoLines[i] = (Entry->InfoLines[i]) ? StrDuplicate(Entry->InfoLines[i]) : NULL; + } // for + NewEntry->Entries = (REFIT_MENU_ENTRY**) AllocateZeroPool(Entry->EntryCount * (sizeof (REFIT_MENU_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() + +// Creates a copy of a menu entry. Intended to enable moving a stack-based +// menu entry (such as the ones for the "reboot" and "exit" functions) to +// to the heap. This enables easier deletion of the whole set of menu +// entries when re-scanning. +// Returns a pointer to the copy of the menu entry. +static REFIT_MENU_ENTRY* CopyMenuEntry(REFIT_MENU_ENTRY *Entry) { + REFIT_MENU_ENTRY *NewEntry; + + NewEntry = AllocateZeroPool(sizeof(REFIT_MENU_ENTRY)); + if ((Entry != NULL) && (NewEntry != NULL)) { + CopyMem(NewEntry, Entry, sizeof(REFIT_MENU_ENTRY)); + NewEntry->Title = (Entry->Title) ? StrDuplicate(Entry->Title) : NULL; + if (Entry->BadgeImage != NULL) { + NewEntry->BadgeImage = AllocatePool(sizeof(EG_IMAGE)); + if (NewEntry->BadgeImage != NULL) + CopyMem(NewEntry->BadgeImage, Entry->BadgeImage, sizeof(EG_IMAGE)); + } + if (Entry->Image != NULL) { + NewEntry->Image = AllocatePool(sizeof(EG_IMAGE)); + if (NewEntry->Image != NULL) + CopyMem(NewEntry->Image, Entry->Image, sizeof(EG_IMAGE)); + } + if (Entry->SubScreen != NULL) { + NewEntry->SubScreen = CopyMenuScreen(Entry->SubScreen); + } + } // if + return (NewEntry); +} // REFIT_MENU_ENTRY* CopyMenuEntry() + +// Creates a new LOADER_ENTRY data structure and populates it with +// default values from the specified Entry, or NULL values if Entry +// is unspecified (NULL). +// Returns a pointer to the new data structure, or NULL if it +// couldn't be allocated +LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry) { + LOADER_ENTRY *NewEntry = NULL; + + NewEntry = AllocateZeroPool(sizeof(LOADER_ENTRY)); + if (NewEntry != NULL) { + NewEntry->me.Title = NULL; + NewEntry->me.Tag = TAG_LOADER; + NewEntry->Enabled = TRUE; + NewEntry->UseGraphicsMode = FALSE; + NewEntry->OSType = 0; + NewEntry->DiscoveryType = DISCOVERY_TYPE_UNKNOWN; + if (Entry != NULL) { + NewEntry->LoaderPath = (Entry->LoaderPath) ? StrDuplicate(Entry->LoaderPath) : NULL; + NewEntry->VolName = (Entry->VolName) ? StrDuplicate(Entry->VolName) : NULL; + NewEntry->DevicePath = Entry->DevicePath; + NewEntry->UseGraphicsMode = Entry->UseGraphicsMode; + NewEntry->LoadOptions = (Entry->LoadOptions) ? StrDuplicate(Entry->LoadOptions) : NULL; + NewEntry->InitrdPath = (Entry->InitrdPath) ? StrDuplicate(Entry->InitrdPath) : NULL; + NewEntry->DiscoveryType = Entry->DiscoveryType; + } + } // if + 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. +// If a subscreen already exists in the Entry that's passed to this function, +// it's left unchanged and a pointer to it is returned. +// 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, *MainOptions = NULL; + REFIT_MENU_SCREEN *SubScreen = NULL; + LOADER_ENTRY *SubEntry; + + FileName = Basename(Entry->LoaderPath); + if (Entry->me.SubScreen == NULL) { // No subscreen yet; initialize default entry.... + SubScreen = AllocateZeroPool(sizeof(REFIT_MENU_SCREEN)); + if (SubScreen != NULL) { + SubScreen->Title = AllocateZeroPool(sizeof(CHAR16) * 256); + SPrint(SubScreen->Title, 255, L"Boot Options for %s on %s", + (Entry->Title != NULL) ? Entry->Title : FileName, Entry->VolName); + SubScreen->TitleImage = Entry->me.Image; + // default entry + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + 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; + } // if/else + return SubScreen; +} // REFIT_MENU_SCREEN *InitializeSubScreen() + +VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN GenerateReturn) { + REFIT_MENU_SCREEN *SubScreen; + LOADER_ENTRY *SubEntry; + CHAR16 *InitrdName, *KernelVersion = NULL; + CHAR16 DiagsFileName[256]; + REFIT_FILE *File; + UINTN TokenCount; + CHAR16 **TokenList; + + // create the submenu + if (StrLen(Entry->Title) == 0) { + MyFreePool(Entry->Title); + Entry->Title = NULL; + } + SubScreen = InitializeSubScreen(Entry); + + // loader-specific submenu entries + if (Entry->OSType == 'M') { // entries for macOS +#if defined(EFIX64) + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot macOS with a 64-bit kernel"; + SubEntry->LoadOptions = L"arch=x86_64"; + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // if + + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot macOS with a 32-bit kernel"; + SubEntry->LoadOptions = L"arch=i386"; + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // if +#endif + + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_SINGLEUSER)) { + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot macOS in verbose mode"; + SubEntry->UseGraphicsMode = FALSE; + SubEntry->LoadOptions = L"-v"; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // if + +#if defined(EFIX64) + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot macOS in verbose mode (64-bit)"; + SubEntry->UseGraphicsMode = FALSE; + SubEntry->LoadOptions = L"-v arch=x86_64"; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } + + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot macOS in verbose mode (32-bit)"; + SubEntry->UseGraphicsMode = FALSE; + SubEntry->LoadOptions = L"-v arch=i386"; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } +#endif + + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot macOS in single user mode"; + SubEntry->UseGraphicsMode = FALSE; + SubEntry->LoadOptions = L"-v -s"; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // if + } // single-user mode allowed + + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_SAFEMODE)) { + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot macOS in safe mode"; + SubEntry->UseGraphicsMode = FALSE; + SubEntry->LoadOptions = L"-v -x"; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // if + } // safe mode allowed + + // check for Apple hardware diagnostics + 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) { + SubEntry->me.Title = L"Run Apple Hardware Test"; + MyFreePool(SubEntry->LoaderPath); + SubEntry->LoaderPath = StrDuplicate(DiagsFileName); + SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath); + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // if + } // if diagnostics entry found + + } else if (Entry->OSType == 'L') { // entries for Linux kernels with EFI stub loaders + File = ReadLinuxOptionsFile(Entry->LoaderPath, Volume); + if (File != NULL) { + InitrdName = FindInitrd(Entry->LoaderPath, Volume); + TokenCount = ReadTokenLine(File, &TokenList); + KernelVersion = FindNumbers(Entry->LoaderPath); + ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion); + // first entry requires special processing, since it was initially set + // up with a default title but correct options by InitializeSubScreen(), + // earlier.... + if ((TokenCount > 1) && (SubScreen->Entries != NULL) && (SubScreen->Entries[0] != NULL)) { + MyFreePool(SubScreen->Entries[0]->Title); + SubScreen->Entries[0]->Title = TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux"); + } // if + FreeTokenLine(&TokenList, &TokenCount); + while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { + ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion); + SubEntry = InitializeLoaderEntry(Entry); + SubEntry->me.Title = TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux"); + MyFreePool(SubEntry->LoadOptions); + SubEntry->LoadOptions = AddInitrdToOptions(TokenList[1], InitrdName); + FreeTokenLine(&TokenList, &TokenCount); + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // while + MyFreePool(KernelVersion); + MyFreePool(InitrdName); + MyFreePool(File); + } // if + + } else if (Entry->OSType == 'E') { // entries for ELILO + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Run ELILO in interactive mode"; + SubEntry->LoadOptions = L"-p"; + 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 17\" iMac or a 15\" MacBook Pro (*)"; + 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->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->LoadOptions = L"-d 0 mini"; + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } + + AddMenuInfoLine(SubScreen, L"NOTE: This is an example. Entries"); + AddMenuInfoLine(SubScreen, L"marked with (*) may not work."); + + } else if (Entry->OSType == 'X') { // entries for xom.efi + // by default, skip the built-in selection and boot from hard disk only + Entry->LoadOptions = L"-s -h"; + + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot Windows from Hard Disk"; + SubEntry->LoadOptions = L"-s -h"; + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } + + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Boot Windows from CD-ROM"; + SubEntry->LoadOptions = L"-s -c"; + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } + + SubEntry = InitializeLoaderEntry(Entry); + if (SubEntry != NULL) { + SubEntry->me.Title = L"Run XOM in text mode"; + SubEntry->LoadOptions = L"-v"; + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } + } // entries for xom.efi + if (GenerateReturn) + AddMenuEntry(SubScreen, &MenuEntryReturn); + Entry->me.SubScreen = SubScreen; +} // VOID GenerateSubScreen() + +// Returns options for a Linux kernel. Reads them from an options file in the +// 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, *FullOptions = NULL, *KernelVersion; + + Options = GetFirstOptionsFromFile(LoaderPath, Volume); + InitrdName = FindInitrd(LoaderPath, Volume); + KernelVersion = FindNumbers(InitrdName); + ReplaceSubstring(&Options, KERNEL_VERSION, KernelVersion); + FullOptions = AddInitrdToOptions(Options, InitrdName); + + MyFreePool(Options); + MyFreePool(InitrdName); + MyFreePool(KernelVersion); + return (FullOptions); +} // static CHAR16 * GetMainLinuxOptions() + +// Read the specified file and add values of "ID", "NAME", or "DISTRIB_ID" tokens to +// OSIconName list. Intended for adding Linux distribution clues gleaned from +// /etc/lsb-release and /etc/os-release files. +static VOID ParseReleaseFile(CHAR16 **OSIconName, REFIT_VOLUME *Volume, CHAR16 *FileName) { + UINTN FileSize = 0; + REFIT_FILE File; + CHAR16 **TokenList; + UINTN TokenCount = 0; + + if ((Volume == NULL) || (FileName == NULL) || (OSIconName == NULL) || (*OSIconName == NULL)) + return; + + if (FileExists(Volume->RootDir, FileName) && + (ReadFile(Volume->RootDir, FileName, &File, &FileSize) == EFI_SUCCESS)) { + do { + TokenCount = ReadTokenLine(&File, &TokenList); + if ((TokenCount > 1) && (MyStriCmp(TokenList[0], L"ID") || + MyStriCmp(TokenList[0], L"NAME") || + MyStriCmp(TokenList[0], L"DISTRIB_ID"))) { + MergeWords(OSIconName, TokenList[1], L','); + } // if + FreeTokenLine(&TokenList, &TokenCount); + } while (TokenCount > 0); + MyFreePool(File.Buffer); + } // if +} // VOID ParseReleaseFile() + +// Try to guess the name of the Linux distribution & add that name to +// OSIconName list. +static VOID GuessLinuxDistribution(CHAR16 **OSIconName, REFIT_VOLUME *Volume, CHAR16 *LoaderPath) { + // If on Linux root fs, /etc/os-release or /etc/lsb-release file probably has clues.... + ParseReleaseFile(OSIconName, Volume, L"etc\\lsb-release"); + ParseReleaseFile(OSIconName, Volume, L"etc\\os-release"); + + // Search for clues in the kernel's filename.... + if (StriSubCmp(L".fc", LoaderPath)) + MergeStrings(OSIconName, L"fedora", L','); + if (StriSubCmp(L".el", LoaderPath)) + MergeStrings(OSIconName, L"redhat", L','); +} // VOID GuessLinuxDistribution() + +// 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, REFIT_VOLUME *Volume) { + CHAR16 *NameClues, *PathOnly, *NoExtension, *OSIconName = NULL, *Temp; + CHAR16 ShortcutLetter = 0; + + NameClues = Basename(LoaderPath); + PathOnly = FindPath(LoaderPath); + NoExtension = StripEfiExtension(NameClues); + + if (Volume->DiskKind == DISK_KIND_NET) { + MergeStrings(&NameClues, Entry->me.Title, L' '); + } else { + // locate a custom icon for the loader + // Anything found here takes precedence over the "hints" in the OSIconName variable + if (!Entry->me.Image) { + Entry->me.Image = egLoadIconAnyType(Volume->RootDir, PathOnly, NoExtension, GlobalConfig.IconSizes[ICON_SIZE_BIG]); + } + if (!Entry->me.Image) { + Entry->me.Image = egCopyImage(Volume->VolIconImage); + } + + // Begin creating icon "hints" by using last part of directory path leading + // to the loader + Temp = FindLastDirName(LoaderPath); + MergeStrings(&OSIconName, Temp, L','); + MyFreePool(Temp); + Temp = NULL; + if (OSIconName != NULL) { + 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. + MergeWords(&OSIconName, Volume->VolName, L','); + } // if/else network boot + + // detect specific loaders + if (StriSubCmp(L"bzImage", NameClues) || StriSubCmp(L"vmlinuz", NameClues) || StriSubCmp(L"kernel", NameClues)) { + if (Volume->DiskKind != DISK_KIND_NET) { + GuessLinuxDistribution(&OSIconName, Volume, LoaderPath); + Entry->LoadOptions = GetMainLinuxOptions(LoaderPath, Volume); + } + MergeStrings(&OSIconName, L"linux", L','); + Entry->OSType = 'L'; + if (ShortcutLetter == 0) + ShortcutLetter = 'L'; + Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; + } else if (StriSubCmp(L"refit", LoaderPath)) { + MergeStrings(&OSIconName, L"refit", L','); + Entry->OSType = 'R'; + ShortcutLetter = 'R'; + } else if (StriSubCmp(L"refind", LoaderPath)) { + MergeStrings(&OSIconName, L"refind", L','); + Entry->OSType = 'R'; + ShortcutLetter = 'R'; + } else if (MyStriCmp(LoaderPath, MACOSX_LOADER_PATH)) { + MergeStrings(&OSIconName, L"mac", L','); + Entry->OSType = 'M'; + ShortcutLetter = 'M'; + Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; + } else if (MyStriCmp(NameClues, L"diags.efi")) { + MergeStrings(&OSIconName, L"hwtest", L','); + } else if (MyStriCmp(NameClues, L"e.efi") || MyStriCmp(NameClues, L"elilo.efi") || StriSubCmp(L"elilo", NameClues)) { + MergeStrings(&OSIconName, L"elilo,linux", L','); + Entry->OSType = 'E'; + if (ShortcutLetter == 0) + ShortcutLetter = 'L'; + Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO; + } else if (StriSubCmp(L"grub", NameClues)) { + MergeStrings(&OSIconName, L"grub,linux", L','); + Entry->OSType = 'G'; + ShortcutLetter = 'G'; + Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_GRUB; + } else if (MyStriCmp(NameClues, L"cdboot.efi") || + MyStriCmp(NameClues, L"bootmgr.efi") || + MyStriCmp(NameClues, L"bootmgfw.efi") || + MyStriCmp(NameClues, L"bkpbootmgfw.efi")) { + MergeStrings(&OSIconName, L"win8", L','); + Entry->OSType = 'W'; + ShortcutLetter = 'W'; + Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; + } else if (MyStriCmp(NameClues, L"xom.efi")) { + MergeStrings(&OSIconName, L"xom,win,win8", L','); + Entry->OSType = 'X'; + ShortcutLetter = 'W'; + Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; + } + else if (StriSubCmp(L"ipxe", NameClues)) { + Entry->OSType = 'N'; + ShortcutLetter = 'N'; + MergeStrings(&OSIconName, L"network", L','); + } + + if ((ShortcutLetter >= 'a') && (ShortcutLetter <= 'z')) + ShortcutLetter = ShortcutLetter - 'a' + 'A'; // convert lowercase to uppercase + Entry->me.ShortcutLetter = ShortcutLetter; + if (Entry->me.Image == NULL) + Entry->me.Image = LoadOSIcon(OSIconName, L"unknown", FALSE); + MyFreePool(PathOnly); +} // VOID SetLoaderDefaults() + +// Add a specified EFI boot loader to the list, using automatic settings +// for icons, options, etc. +static LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume, IN BOOLEAN SubScreenReturn) { + LOADER_ENTRY *Entry; + + CleanUpPathNameSlashes(LoaderPath); + Entry = InitializeLoaderEntry(NULL); + Entry->DiscoveryType = DISCOVERY_TYPE_AUTO; + if (Entry != NULL) { + Entry->Title = StrDuplicate((LoaderTitle != NULL) ? LoaderTitle : LoaderPath); + Entry->me.Title = AllocateZeroPool(sizeof(CHAR16) * 256); + // Extra space at end of Entry->me.Title enables searching on Volume->VolName even if another volume + // name is identical except for something added to the end (e.g., VolB1 vs. VolB12). + // Note: Volume->VolName will be NULL for network boot programs. + if ((Volume->VolName) && (!MyStriCmp(Volume->VolName, L"Recovery HD"))) + SPrint(Entry->me.Title, 255, L"Boot %s from %s ", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath, Volume->VolName); + else + SPrint(Entry->me.Title, 255, L"Boot %s ", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath); + Entry->me.Row = 0; + Entry->me.BadgeImage = Volume->VolBadgeImage; + if ((LoaderPath != NULL) && (LoaderPath[0] != L'\\')) { + Entry->LoaderPath = StrDuplicate(L"\\"); + } else { + Entry->LoaderPath = NULL; + } + MergeStrings(&(Entry->LoaderPath), LoaderPath, 0); + Entry->VolName = Volume->VolName; + Entry->DevicePath = FileDevicePath(Volume->DeviceHandle, Entry->LoaderPath); + SetLoaderDefaults(Entry, LoaderPath, Volume); + GenerateSubScreen(Entry, Volume, SubScreenReturn); + AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); + } + + return(Entry); +} // LOADER_ENTRY * AddLoaderEntry() + +// Add a Linux kernel as a submenu entry for another (pre-existing) Linux kernel entry. +static VOID AddKernelToSubmenu(LOADER_ENTRY * TargetLoader, CHAR16 *FileName, REFIT_VOLUME *Volume) { + REFIT_FILE *File; + CHAR16 **TokenList = NULL, *InitrdName, *SubmenuName = NULL, *VolName = NULL; + CHAR16 *Path = NULL, *Title, *KernelVersion; + REFIT_MENU_SCREEN *SubScreen; + LOADER_ENTRY *SubEntry; + UINTN TokenCount; + + File = ReadLinuxOptionsFile(TargetLoader->LoaderPath, Volume); + if (File != NULL) { + SubScreen = TargetLoader->me.SubScreen; + InitrdName = FindInitrd(FileName, Volume); + KernelVersion = FindNumbers(FileName); + while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { + ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion); + SubEntry = InitializeLoaderEntry(TargetLoader); + SplitPathName(FileName, &VolName, &Path, &SubmenuName); + MergeStrings(&SubmenuName, L": ", '\0'); + MergeStrings(&SubmenuName, TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux"), '\0'); + Title = StrDuplicate(SubmenuName); + LimitStringLength(Title, MAX_LINE_LENGTH); + SubEntry->me.Title = Title; + MyFreePool(SubEntry->LoadOptions); + SubEntry->LoadOptions = AddInitrdToOptions(TokenList[1], InitrdName); + MyFreePool(SubEntry->LoaderPath); + SubEntry->LoaderPath = StrDuplicate(FileName); + CleanUpPathNameSlashes(SubEntry->LoaderPath); + SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath); + FreeTokenLine(&TokenList, &TokenCount); + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // while + MyFreePool(VolName); + MyFreePool(Path); + MyFreePool(SubmenuName); + MyFreePool(InitrdName); + MyFreePool(File); + MyFreePool(KernelVersion); + } // if +} // static VOID AddKernelToSubmenu() + +// Returns -1 if (Time1 < Time2), +1 if (Time1 > Time2), or 0 if +// (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(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 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) + + (Time2->Month * 2678400) + ((Time2->Year - 1998) * 32140800); + if (Time1InSeconds < Time2InSeconds) + return (-1); + else if (Time1InSeconds > Time2InSeconds) + return (1); + + return 0; +} // INTN TimeComp() + +// Adds a loader list element, keeping it sorted by date. EXCEPTION: Fedora's rescue +// kernel, which begins with "vmlinuz-0-rescue," should not be at the top of the list, +// since that will make it the default if kernel folding is enabled, so float it to +// the end. +// Returns the new first element (the one with the most recent date). +static struct LOADER_LIST * AddLoaderListEntry(struct LOADER_LIST *LoaderList, struct LOADER_LIST *NewEntry) { + struct LOADER_LIST *LatestEntry, *CurrentEntry, *PrevEntry = NULL; + BOOLEAN LinuxRescue = FALSE; + + LatestEntry = CurrentEntry = LoaderList; + if (LoaderList == NULL) { + LatestEntry = NewEntry; + } else { + if (StriSubCmp(L"vmlinuz-0-rescue", NewEntry->FileName)) + LinuxRescue = TRUE; + while ((CurrentEntry != NULL) && !StriSubCmp(L"vmlinuz-0-rescue", CurrentEntry->FileName) && + (LinuxRescue || (TimeComp(&(NewEntry->TimeStamp), &(CurrentEntry->TimeStamp)) < 0))) { + PrevEntry = CurrentEntry; + CurrentEntry = CurrentEntry->NextEntry; + } // while + NewEntry->NextEntry = CurrentEntry; + if (PrevEntry == NULL) { + LatestEntry = NewEntry; + } else { + PrevEntry->NextEntry = NewEntry; + } // if/else + } // if/else + return (LatestEntry); +} // static VOID AddLoaderListEntry() + +// Delete the LOADER_LIST linked list +static VOID CleanUpLoaderList(struct LOADER_LIST *LoaderList) { + struct LOADER_LIST *Temp; + + while (LoaderList != NULL) { + Temp = LoaderList; + LoaderList = LoaderList->NextEntry; + MyFreePool(Temp->FileName); + MyFreePool(Temp); + } // while +} // static VOID CleanUpLoaderList() + +// Returns FALSE if the specified file/volume matches the GlobalConfig.DontScanDirs +// or GlobalConfig.DontScanVolumes specification, or if Path points to a volume +// other than the one specified by Volume, or if the specified path is SelfDir. +// Returns TRUE if none of these conditions is met -- that is, if the path is +// eligible for scanning. +static BOOLEAN ShouldScan(REFIT_VOLUME *Volume, CHAR16 *Path) { + CHAR16 *VolName = NULL, *DontScanDir, *PathCopy = NULL, *VolGuid = NULL; + UINTN i = 0; + BOOLEAN ScanIt = TRUE; + + VolGuid = GuidAsString(&(Volume->PartGuid)); + if ((IsIn(Volume->VolName, GlobalConfig.DontScanVolumes)) || (IsIn(Volume->PartName, GlobalConfig.DontScanVolumes)) || + (IsIn(VolGuid, GlobalConfig.DontScanVolumes))) { + MyFreePool(VolGuid); + return FALSE; + } else { + MyFreePool(VolGuid); + } // if/else + + if (MyStriCmp(Path, SelfDirPath) && (Volume->DeviceHandle == SelfVolume->DeviceHandle)) + return FALSE; + + // See if Path includes an explicit volume declaration that's NOT Volume.... + PathCopy = StrDuplicate(Path); + if (SplitVolumeAndFilename(&PathCopy, &VolName)) { + if (VolName && !MyStriCmp(VolName, Volume->VolName)) { + ScanIt = FALSE; + } // if + } // if Path includes volume specification + MyFreePool(PathCopy); + MyFreePool(VolName); + VolName = NULL; + + // See if Volume is in GlobalConfig.DontScanDirs.... + while (ScanIt && (DontScanDir = FindCommaDelimited(GlobalConfig.DontScanDirs, i++))) { + SplitVolumeAndFilename(&DontScanDir, &VolName); + CleanUpPathNameSlashes(DontScanDir); + if (VolName != NULL) { + if (VolumeMatchesDescription(Volume, VolName) && MyStriCmp(DontScanDir, Path)) + ScanIt = FALSE; + } else { + if (MyStriCmp(DontScanDir, Path)) + ScanIt = FALSE; + } + MyFreePool(DontScanDir); + MyFreePool(VolName); + DontScanDir = NULL; + VolName = NULL; + } // while() + + return ScanIt; +} // BOOLEAN ShouldScan() + +// Returns TRUE if the file is byte-for-byte identical with the fallback file +// on the volume AND if the file is not itself the fallback file; returns +// FALSE if the file is not identical to the fallback file OR if the file +// IS the fallback file. Intended for use in excluding the fallback boot +// loader when it's a duplicate of another boot loader. +static BOOLEAN DuplicatesFallback(IN REFIT_VOLUME *Volume, IN CHAR16 *FileName) { + CHAR8 *FileContents, *FallbackContents; + EFI_FILE_HANDLE FileHandle, FallbackHandle; + EFI_FILE_INFO *FileInfo, *FallbackInfo; + UINTN FileSize = 0, FallbackSize = 0; + EFI_STATUS Status; + BOOLEAN AreIdentical = FALSE; + + if (!FileExists(Volume->RootDir, FileName) || !FileExists(Volume->RootDir, FALLBACK_FULLNAME)) + return FALSE; + + CleanUpPathNameSlashes(FileName); + + if (MyStriCmp(FileName, FALLBACK_FULLNAME)) + return FALSE; // identical filenames, so not a duplicate.... + + Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (Status == EFI_SUCCESS) { + FileInfo = LibFileInfo(FileHandle); + FileSize = FileInfo->FileSize; + } else { + return FALSE; + } + + Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FallbackHandle, FALLBACK_FULLNAME, EFI_FILE_MODE_READ, 0); + if (Status == EFI_SUCCESS) { + FallbackInfo = LibFileInfo(FallbackHandle); + FallbackSize = FallbackInfo->FileSize; + } else { + refit_call1_wrapper(FileHandle->Close, FileHandle); + return FALSE; + } + + if (FallbackSize == FileSize) { // could be identical; do full check.... + FileContents = AllocatePool(FileSize); + FallbackContents = AllocatePool(FallbackSize); + if (FileContents && FallbackContents) { + Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &FileSize, FileContents); + if (Status == EFI_SUCCESS) { + Status = refit_call3_wrapper(FallbackHandle->Read, FallbackHandle, &FallbackSize, FallbackContents); + } + if (Status == EFI_SUCCESS) { + AreIdentical = (CompareMem(FileContents, FallbackContents, FileSize) == 0); + } // if + } // if + MyFreePool(FileContents); + MyFreePool(FallbackContents); + } // if/else + + // BUG ALERT: Some systems (e.g., DUET, some Macs with large displays) crash if the + // following two calls are reversed. Go figure.... + refit_call1_wrapper(FileHandle->Close, FallbackHandle); + refit_call1_wrapper(FileHandle->Close, FileHandle); + return AreIdentical; +} // BOOLEAN DuplicatesFallback() + +// Returns FALSE if two measures of file size are identical for a single file, +// TRUE if not or if the file can't be opened and the other measure is non-0. +// Despite the function's name, this isn't really a direct test of symbolic +// link status, since EFI doesn't officially support symlinks. It does seem +// to be a reliable indicator, though. (OTOH, some disk errors might cause a +// file to fail to open, which would return a false positive -- but as I use +// this function to exclude symbolic links from the list of boot loaders, +// that would be fine, since such boot loaders wouldn't work.) +// CAUTION: *FullName MUST be properly cleaned up (via CleanUpPathNameSlashes()) +static BOOLEAN IsSymbolicLink(REFIT_VOLUME *Volume, CHAR16 *FullName, EFI_FILE_INFO *DirEntry) { + EFI_FILE_HANDLE FileHandle; + EFI_FILE_INFO *FileInfo = NULL; + EFI_STATUS Status; + UINTN FileSize2 = 0; + + Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FileHandle, FullName, EFI_FILE_MODE_READ, 0); + if (Status == EFI_SUCCESS) { + FileInfo = LibFileInfo(FileHandle); + if (FileInfo != NULL) + FileSize2 = FileInfo->FileSize; + } + + MyFreePool(FileInfo); + + return (DirEntry->FileSize != FileSize2); +} // BOOLEAN IsSymbolicLink() + +// Returns TRUE if a file with the same name as the original but with +// ".efi.signed" is also present in the same directory. Ubuntu is using +// this filename as a signed version of the original unsigned kernel, and +// there's no point in cluttering the display with two kernels that will +// behave identically on non-SB systems, or when one will fail when SB +// is active. +// CAUTION: *FullName MUST be properly cleaned up (via CleanUpPathNameSlashes()) +static BOOLEAN HasSignedCounterpart(IN REFIT_VOLUME *Volume, IN CHAR16 *FullName) { + CHAR16 *NewFile = NULL; + BOOLEAN retval = FALSE; + + MergeStrings(&NewFile, FullName, 0); + MergeStrings(&NewFile, L".efi.signed", 0); + if (NewFile != NULL) { + if (FileExists(Volume->RootDir, NewFile)) + retval = TRUE; + MyFreePool(NewFile); + } // if + + return retval; +} // BOOLEAN HasSignedCounterpart() + +// Scan an individual directory for EFI boot loader files and, if found, +// add them to the list. Exception: Ignores FALLBACK_FULLNAME, which is picked +// up in ScanEfiFiles(). Sorts the entries within the loader directory so that +// the most recent one appears first in the list. +// Returns TRUE if a duplicate for FALLBACK_FILENAME was found, FALSE if not. +static BOOLEAN ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *Pattern) +{ + EFI_STATUS Status; + REFIT_DIR_ITER DirIter; + EFI_FILE_INFO *DirEntry; + CHAR16 Message[256], *Extension, *FullName; + struct LOADER_LIST *LoaderList = NULL, *NewLoader; + LOADER_ENTRY *FirstKernel = NULL, *LatestEntry = NULL; + BOOLEAN FoundFallbackDuplicate = FALSE, IsLinux = FALSE, InSelfPath; + + InSelfPath = MyStriCmp(Path, SelfDirPath); + if ((!SelfDirPath || !Path || (InSelfPath && (Volume->DeviceHandle != SelfVolume->DeviceHandle)) || + (!InSelfPath)) && (ShouldScan(Volume, Path))) { + // look through contents of the directory + DirIterOpen(Volume->RootDir, Path, &DirIter); + while (DirIterNext(&DirIter, 2, Pattern, &DirEntry)) { + Extension = FindExtension(DirEntry->FileName); + FullName = StrDuplicate(Path); + MergeStrings(&FullName, DirEntry->FileName, L'\\'); + CleanUpPathNameSlashes(FullName); + if (DirEntry->FileName[0] == '.' || + MyStriCmp(Extension, L".icns") || + MyStriCmp(Extension, L".png") || + (MyStriCmp(DirEntry->FileName, FALLBACK_BASENAME) && (MyStriCmp(Path, L"EFI\\BOOT"))) || + FilenameIn(Volume, Path, DirEntry->FileName, SHELL_NAMES) || + IsSymbolicLink(Volume, FullName, DirEntry) || /* is symbolic link */ + HasSignedCounterpart(Volume, FullName) || /* a file with same name plus ".efi.signed" is present */ + FilenameIn(Volume, Path, DirEntry->FileName, GlobalConfig.DontScanFiles) || + !IsValidLoader(Volume->RootDir, FullName)) { + continue; // skip this + } + + NewLoader = AllocateZeroPool(sizeof(struct LOADER_LIST)); + if (NewLoader != NULL) { + NewLoader->FileName = StrDuplicate(FullName); + NewLoader->TimeStamp = DirEntry->ModificationTime; + LoaderList = AddLoaderListEntry(LoaderList, NewLoader); + if (DuplicatesFallback(Volume, FullName)) + FoundFallbackDuplicate = TRUE; + } // if + MyFreePool(Extension); + MyFreePool(FullName); + } // while + + NewLoader = LoaderList; + while (NewLoader != NULL) { + IsLinux = (StriSubCmp(L"bzImage", NewLoader->FileName) || + StriSubCmp(L"vmlinuz", NewLoader->FileName) || + StriSubCmp(L"kernel", NewLoader->FileName)); + if ((FirstKernel != NULL) && IsLinux && GlobalConfig.FoldLinuxKernels) { + AddKernelToSubmenu(FirstKernel, NewLoader->FileName, Volume); + } else { + LatestEntry = AddLoaderEntry(NewLoader->FileName, NULL, Volume, !(IsLinux && GlobalConfig.FoldLinuxKernels)); + if (IsLinux && (FirstKernel == NULL)) + FirstKernel = LatestEntry; + } + NewLoader = NewLoader->NextEntry; + } // while + if ((NewLoader != NULL) && (FirstKernel != NULL) && IsLinux && GlobalConfig.FoldLinuxKernels) + AddMenuEntry(FirstKernel->me.SubScreen, &MenuEntryReturn); + + CleanUpLoaderList(LoaderList); + Status = DirIterClose(&DirIter); + // NOTE: EFI_INVALID_PARAMETER really is an error that should be reported; + // but I've gotten reports from users who are getting this error occasionally + // and I can't find anything wrong or reproduce the problem, so I'm putting + // it down to buggy EFI implementations and ignoring that particular error.... + if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { + if (Path) + SPrint(Message, 255, L"while scanning the %s directory on %s", Path, Volume->VolName); + else + SPrint(Message, 255, L"while scanning the root directory on %s", Path, Volume->VolName); + CheckError(Status, Message); + } // if (Status != EFI_NOT_FOUND) + } // if not scanning a blacklisted directory + + return FoundFallbackDuplicate; +} /* static VOID ScanLoaderDir() */ + +// Run the IPXE_DISCOVER_NAME program, which obtains the IP address of the boot +// server and the name of the boot file it delivers. +CHAR16* RuniPXEDiscover(EFI_HANDLE Volume) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *FilePath; + EFI_HANDLE iPXEHandle; + CHAR16 *boot_info = NULL; + UINTN boot_info_size = 0; + + FilePath = FileDevicePath (Volume, IPXE_DISCOVER_NAME); + Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, FilePath, NULL, 0, &iPXEHandle); + if (Status != 0) + return NULL; + + Status = refit_call3_wrapper(BS->StartImage, iPXEHandle, &boot_info_size, &boot_info); + + return boot_info; +} // RuniPXEDiscover() + +// Scan for network (PXE) boot servers. This function relies on the presence +// of the IPXE_DISCOVER_NAME and IPXE_NAME program files on the volume from +// which rEFInd launched. As of December 6, 2014, these tools aren't entirely +// reliable. See BUILDING.txt for information on building them. +static VOID ScanNetboot() { + CHAR16 *iPXEFileName = IPXE_NAME; + CHAR16 *Location; + REFIT_VOLUME *NetVolume; + + if (FileExists(SelfVolume->RootDir, IPXE_DISCOVER_NAME) && + FileExists(SelfVolume->RootDir, IPXE_NAME) && + IsValidLoader(SelfVolume->RootDir, IPXE_DISCOVER_NAME) && + IsValidLoader(SelfVolume->RootDir, IPXE_NAME)) { + Location = RuniPXEDiscover(SelfVolume->DeviceHandle); + if (Location != NULL && FileExists(SelfVolume->RootDir, iPXEFileName)) { + NetVolume = AllocatePool(sizeof(REFIT_VOLUME)); + CopyMem(NetVolume, SelfVolume, sizeof(REFIT_VOLUME)); + NetVolume->DiskKind = DISK_KIND_NET; + NetVolume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_NET); + NetVolume->PartName = NetVolume->VolName = NULL; + AddLoaderEntry(iPXEFileName, Location, NetVolume, TRUE); + MyFreePool(NetVolume); + } // if support files exist and are valid + } +} // VOID ScanNetBoot() + +static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { + EFI_STATUS Status; + REFIT_DIR_ITER EfiDirIter; + EFI_FILE_INFO *EfiDirEntry; + CHAR16 FileName[256], *Directory = NULL, *MatchPatterns, *VolName = NULL, *SelfPath, *Temp; + UINTN i, Length; + BOOLEAN ScanFallbackLoader = TRUE; + BOOLEAN FoundBRBackup = FALSE; + + if (Volume && (Volume->RootDir != NULL) && (Volume->VolName != NULL) && (Volume->IsReadable)) { + MatchPatterns = StrDuplicate(LOADER_MATCH_PATTERNS); + if (GlobalConfig.ScanAllLinux) + MergeStrings(&MatchPatterns, LINUX_MATCH_PATTERNS, L','); + + // check for macOS boot loader + if (ShouldScan(Volume, MACOSX_LOADER_DIR)) { + StrCpy(FileName, MACOSX_LOADER_PATH); + if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, MACOSX_LOADER_DIR, L"boot.efi", GlobalConfig.DontScanFiles)) { + AddLoaderEntry(FileName, L"macOS", Volume, TRUE); + if (DuplicatesFallback(Volume, FileName)) + ScanFallbackLoader = FALSE; + } + + // check for XOM + StrCpy(FileName, L"System\\Library\\CoreServices\\xom.efi"); + if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, MACOSX_LOADER_DIR, L"xom.efi", GlobalConfig.DontScanFiles)) { + AddLoaderEntry(FileName, L"Windows XP (XoM)", Volume, TRUE); + if (DuplicatesFallback(Volume, FileName)) + ScanFallbackLoader = FALSE; + } + } // if should scan Mac directory + + // check for Microsoft boot loader/menu + if (ShouldScan(Volume, L"EFI\\Microsoft\\Boot")) { + StrCpy(FileName, L"EFI\\Microsoft\\Boot\\bkpbootmgfw.efi"); + if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, L"EFI\\Microsoft\\Boot", L"bkpbootmgfw.efi", + GlobalConfig.DontScanFiles)) { + AddLoaderEntry(FileName, L"Microsoft EFI boot (Boot Repair backup)", Volume, TRUE); + FoundBRBackup = TRUE; + if (DuplicatesFallback(Volume, FileName)) + ScanFallbackLoader = FALSE; + } + StrCpy(FileName, L"EFI\\Microsoft\\Boot\\bootmgfw.efi"); + if (FileExists(Volume->RootDir, FileName) && + !FilenameIn(Volume, L"EFI\\Microsoft\\Boot", L"bootmgfw.efi", GlobalConfig.DontScanFiles)) { + if (FoundBRBackup) + AddLoaderEntry(FileName, L"Supposed Microsoft EFI boot (probably GRUB)", Volume, TRUE); + else + AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume, TRUE); + if (DuplicatesFallback(Volume, FileName)) + ScanFallbackLoader = FALSE; + } + } // if + + // scan the root directory for EFI executables + if (ScanLoaderDir(Volume, L"\\", MatchPatterns)) + ScanFallbackLoader = FALSE; + + // scan subdirectories of the EFI directory (as per the standard) + DirIterOpen(Volume->RootDir, L"EFI", &EfiDirIter); + while (DirIterNext(&EfiDirIter, 1, NULL, &EfiDirEntry)) { + if (MyStriCmp(EfiDirEntry->FileName, L"tools") || EfiDirEntry->FileName[0] == '.') + continue; // skip this, doesn't contain boot loaders or is scanned later + SPrint(FileName, 255, L"EFI\\%s", EfiDirEntry->FileName); + if (ScanLoaderDir(Volume, FileName, MatchPatterns)) + ScanFallbackLoader = FALSE; + } // while() + Status = DirIterClose(&EfiDirIter); + if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { + Temp = PoolPrint(L"while scanning the EFI directory on %s", Volume->VolName); + CheckError(Status, Temp); + MyFreePool(Temp); + } // if + + // Scan user-specified (or additional default) directories.... + i = 0; + while ((Directory = FindCommaDelimited(GlobalConfig.AlsoScan, i++)) != NULL) { + if (ShouldScan(Volume, Directory)) { + SplitVolumeAndFilename(&Directory, &VolName); + CleanUpPathNameSlashes(Directory); + Length = StrLen(Directory); + if ((Length > 0) && ScanLoaderDir(Volume, Directory, MatchPatterns)) + ScanFallbackLoader = FALSE; + MyFreePool(VolName); + } // if should scan dir + MyFreePool(Directory); + } // while + + // Don't scan the fallback loader if it's on the same volume and a duplicate of rEFInd itself.... + SelfPath = DevicePathToStr(SelfLoadedImage->FilePath); + CleanUpPathNameSlashes(SelfPath); + if ((Volume->DeviceHandle == SelfLoadedImage->DeviceHandle) && DuplicatesFallback(Volume, SelfPath)) + ScanFallbackLoader = FALSE; + + // If not a duplicate & if it exists & if it's not us, create an entry + // for the fallback boot loader + if (ScanFallbackLoader && FileExists(Volume->RootDir, FALLBACK_FULLNAME) && ShouldScan(Volume, L"EFI\\BOOT") && + !FilenameIn(Volume, L"EFI\\BOOT", FALLBACK_BASENAME, GlobalConfig.DontScanFiles)) { + AddLoaderEntry(FALLBACK_FULLNAME, L"Fallback boot loader", Volume, TRUE); + } + } // if +} // static VOID ScanEfiFiles() + +// Scan internal disks for valid EFI boot loaders.... +static VOID ScanInternal(VOID) { + UINTN VolumeIndex; + + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + if (Volumes[VolumeIndex]->DiskKind == DISK_KIND_INTERNAL) { + ScanEfiFiles(Volumes[VolumeIndex]); + } + } // for +} // static VOID ScanInternal() + +// Scan external disks for valid EFI boot loaders.... +static VOID ScanExternal(VOID) { + UINTN VolumeIndex; + + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + if (Volumes[VolumeIndex]->DiskKind == DISK_KIND_EXTERNAL) { + ScanEfiFiles(Volumes[VolumeIndex]); + } + } // for +} // static VOID ScanExternal() + +// Scan internal disks for valid EFI boot loaders.... +static VOID ScanOptical(VOID) { + UINTN VolumeIndex; + + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + if (Volumes[VolumeIndex]->DiskKind == DISK_KIND_OPTICAL) { + ScanEfiFiles(Volumes[VolumeIndex]); + } + } // for +} // static VOID ScanOptical() + +// default volume badge icon based on disk kind +EG_IMAGE * GetDiskBadge(IN UINTN DiskType) { + EG_IMAGE * Badge = NULL; + + switch (DiskType) { + case BBS_HARDDISK: + Badge = BuiltinIcon(BUILTIN_ICON_VOL_INTERNAL); + break; + case BBS_USB: + Badge = BuiltinIcon(BUILTIN_ICON_VOL_EXTERNAL); + break; + case BBS_CDROM: + Badge = BuiltinIcon(BUILTIN_ICON_VOL_OPTICAL); + break; + } // switch() + return Badge; +} // EG_IMAGE * GetDiskBadge() + +// +// pre-boot tool functions +// + +static VOID StartTool(IN LOADER_ENTRY *Entry) +{ + BeginExternalScreen(Entry->UseGraphicsMode, Entry->me.Title + 6); // assumes "Start <title>" as assigned below + StoreLoaderName(Entry->me.Title); + StartEFIImage(Entry->DevicePath, Entry->LoadOptions, TYPE_EFI, + Basename(Entry->LoaderPath), Entry->OSType, NULL, TRUE, FALSE); + FinishExternalScreen(); +} /* static VOID StartTool() */ + +static LOADER_ENTRY * AddToolEntry(EFI_HANDLE DeviceHandle, IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN EG_IMAGE *Image, + IN CHAR16 ShortcutLetter, IN BOOLEAN UseGraphicsMode) +{ + LOADER_ENTRY *Entry; + CHAR16 *TitleStr = NULL; + + Entry = AllocateZeroPool(sizeof(LOADER_ENTRY)); + + TitleStr = PoolPrint(L"Start %s", LoaderTitle); + Entry->me.Title = TitleStr; + Entry->me.Tag = TAG_TOOL; + Entry->me.Row = 1; + Entry->me.ShortcutLetter = ShortcutLetter; + Entry->me.Image = Image; + Entry->LoaderPath = (LoaderPath) ? StrDuplicate(LoaderPath) : NULL; + Entry->DevicePath = FileDevicePath(DeviceHandle, Entry->LoaderPath); + Entry->UseGraphicsMode = UseGraphicsMode; + + AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); + return Entry; +} /* static LOADER_ENTRY * AddToolEntry() */ + +// Locates boot loaders. NOTE: This assumes that GlobalConfig.LegacyType is set correctly. +static VOID ScanForBootloaders(BOOLEAN ShowMessage) { + UINTN i; + CHAR8 s; + BOOLEAN ScanForLegacy = FALSE; + EG_PIXEL BGColor = COLOR_LIGHTBLUE; + CHAR16 *HiddenTags; + + if (ShowMessage) + egDisplayMessage(L"Scanning for boot loaders; please wait....", &BGColor, CENTER); + + // Determine up-front if we'll be scanning for legacy loaders.... + for (i = 0; i < NUM_SCAN_OPTIONS; i++) { + s = GlobalConfig.ScanFor[i]; + if ((s == 'c') || (s == 'C') || (s == 'h') || (s == 'H') || (s == 'b') || (s == 'B')) + ScanForLegacy = TRUE; + } // for + + // If UEFI & scanning for legacy loaders & deep legacy scan, update NVRAM boot manager list + if ((GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) && ScanForLegacy && GlobalConfig.DeepLegacyScan) { + BdsDeleteAllInvalidLegacyBootOptions(); + BdsAddNonExistingLegacyBootOptions(); + } // if + + HiddenTags = ReadHiddenTags(L"HiddenTags"); + if ((HiddenTags) && (StrLen(HiddenTags) > 0)) { + MergeStrings(&GlobalConfig.DontScanFiles, HiddenTags, L','); + } + HiddenTags = ReadHiddenTags(L"HiddenLegacy"); + if ((HiddenTags) && (StrLen(HiddenTags) > 0)) { + MergeStrings(&GlobalConfig.DontScanVolumes, HiddenTags, L','); + } + MyFreePool(HiddenTags); + + // scan for loaders and tools, add them to the menu + for (i = 0; i < NUM_SCAN_OPTIONS; i++) { + switch(GlobalConfig.ScanFor[i]) { + case 'c': case 'C': + ScanLegacyDisc(); + break; + case 'h': case 'H': + ScanLegacyInternal(); + break; + case 'b': case 'B': + ScanLegacyExternal(); + break; + case 'm': case 'M': + ScanUserConfigured(GlobalConfig.ConfigFilename); + break; + case 'e': case 'E': + ScanExternal(); + break; + case 'i': case 'I': + ScanInternal(); + break; + case 'o': case 'O': + ScanOptical(); + break; + case 'n': case 'N': + ScanNetboot(); + break; + } // switch() + } // for + + // assign shortcut keys + for (i = 0; i < MainMenu.EntryCount && MainMenu.Entries[i]->Row == 0 && i < 9; i++) + MainMenu.Entries[i]->ShortcutDigit = (CHAR16)('1' + i); + + // wait for user ACK when there were errors + FinishTextScreen(FALSE); +} // static VOID ScanForBootloaders() + +// Checks to see if a specified file seems to be a valid tool. +// Returns TRUE if it passes all tests, FALSE otherwise +static BOOLEAN IsValidTool(IN REFIT_VOLUME *BaseVolume, CHAR16 *PathName) { + CHAR16 *DontVolName = NULL, *DontPathName = NULL, *DontFileName = NULL, *DontScanThis; + CHAR16 *TestVolName = NULL, *TestPathName = NULL, *TestFileName = NULL; + BOOLEAN retval = TRUE; + UINTN i = 0; + + if (FileExists(BaseVolume->RootDir, PathName) && IsValidLoader(BaseVolume->RootDir, PathName)) { + SplitPathName(PathName, &TestVolName, &TestPathName, &TestFileName); + while (retval && (DontScanThis = FindCommaDelimited(GlobalConfig.DontScanTools, i++))) { + SplitPathName(DontScanThis, &DontVolName, &DontPathName, &DontFileName); + if (MyStriCmp(TestFileName, DontFileName) && + ((DontPathName == NULL) || (MyStriCmp(TestPathName, DontPathName))) && + ((DontVolName == NULL) || (VolumeMatchesDescription(BaseVolume, DontVolName)))) { + retval = FALSE; + } // if + } // while + } else + retval = FALSE; + MyFreePool(TestVolName); + MyFreePool(TestPathName); + MyFreePool(TestFileName); + return retval; +} // VOID IsValidTool() + +// Locate a single tool from the specified Locations using one of the +// specified Names and add it to the menu. +static VOID FindTool(CHAR16 *Locations, CHAR16 *Names, CHAR16 *Description, UINTN Icon) { + UINTN j = 0, k, VolumeIndex; + CHAR16 *DirName, *FileName, *PathName, FullDescription[256]; + + while ((DirName = FindCommaDelimited(Locations, j++)) != NULL) { + k = 0; + while ((FileName = FindCommaDelimited(Names, k++)) != NULL) { + PathName = StrDuplicate(DirName); + MergeStrings(&PathName, FileName, MyStriCmp(PathName, L"\\") ? 0 : L'\\'); + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + if ((Volumes[VolumeIndex]->RootDir != NULL) && (IsValidTool(Volumes[VolumeIndex], PathName))) { + SPrint(FullDescription, 255, L"%s at %s on %s", Description, PathName, Volumes[VolumeIndex]->VolName); + AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, PathName, FullDescription, BuiltinIcon(Icon), 'S', FALSE); + } // if + } // for + MyFreePool(PathName); + MyFreePool(FileName); + } // while Names + MyFreePool(DirName); + } // while Locations +} // VOID FindTool() + +// Add the second-row tags containing built-in and external tools (EFI shell, +// reboot, etc.) +static VOID ScanForTools(VOID) { + CHAR16 *FileName = NULL, *VolName = NULL, *MokLocations, Description[256], *HiddenTools; + REFIT_MENU_ENTRY *TempMenuEntry; + UINTN i, j, VolumeIndex; + UINT64 osind; + CHAR8 *b = 0; + UINT32 CsrValue; + + MokLocations = StrDuplicate(MOK_LOCATIONS); + if (MokLocations != NULL) + MergeStrings(&MokLocations, SelfDirPath, L','); + + HiddenTools = ReadHiddenTags(L"HiddenTools"); + if ((HiddenTools) && (StrLen(HiddenTools) > 0)) { + MergeStrings(&GlobalConfig.DontScanTools, HiddenTools, L','); + } + MyFreePool(HiddenTools); + + for (i = 0; i < NUM_TOOLS; i++) { + switch(GlobalConfig.ShowTools[i]) { + // NOTE: Be sure that FileName is NULL at the end of each case. + case TAG_SHUTDOWN: + TempMenuEntry = CopyMenuEntry(&MenuEntryShutdown); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_SHUTDOWN); + AddMenuEntry(&MainMenu, TempMenuEntry); + break; + + case TAG_REBOOT: + TempMenuEntry = CopyMenuEntry(&MenuEntryReset); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_RESET); + AddMenuEntry(&MainMenu, TempMenuEntry); + break; + + case TAG_ABOUT: + TempMenuEntry = CopyMenuEntry(&MenuEntryAbout); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); + AddMenuEntry(&MainMenu, TempMenuEntry); + break; + + case TAG_EXIT: + TempMenuEntry = CopyMenuEntry(&MenuEntryExit); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_EXIT); + AddMenuEntry(&MainMenu, TempMenuEntry); + break; + + case TAG_HIDDEN: + if (GlobalConfig.HiddenTags) { + TempMenuEntry = CopyMenuEntry(&MenuEntryManageHidden); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_HIDDEN); + AddMenuEntry(&MainMenu, TempMenuEntry); + } + break; + + case TAG_FIRMWARE: + if (EfivarGetRaw(&GlobalGuid, L"OsIndicationsSupported", &b, &j) == EFI_SUCCESS) { + osind = (UINT64)*b; + if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) { + TempMenuEntry = CopyMenuEntry(&MenuEntryFirmware); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_FIRMWARE); + AddMenuEntry(&MainMenu, TempMenuEntry); + } // if + } // if + break; + + case TAG_SHELL: + j = 0; + while ((FileName = FindCommaDelimited(SHELL_NAMES, j++)) != NULL) { + if (IsValidTool(SelfVolume, FileName)) { + AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), + 'S', FALSE); + } + MyFreePool(FileName); + } // while + break; + + case TAG_GPTSYNC: + j = 0; + while ((FileName = FindCommaDelimited(GPTSYNC_NAMES, j++)) != NULL) { + if (IsValidTool(SelfVolume, FileName)) { + AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"Hybrid MBR tool", BuiltinIcon(BUILTIN_ICON_TOOL_PART), + 'P', FALSE); + } // if + MyFreePool(FileName); + } // while + FileName = NULL; + break; + + case TAG_GDISK: + j = 0; + while ((FileName = FindCommaDelimited(GDISK_NAMES, j++)) != NULL) { + if (IsValidTool(SelfVolume, FileName)) { + AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"disk partitioning tool", + BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'G', FALSE); + } // if + MyFreePool(FileName); + } // while + FileName = NULL; + break; + + case TAG_NETBOOT: + j = 0; + while ((FileName = FindCommaDelimited(NETBOOT_NAMES, j++)) != NULL) { + if (IsValidTool(SelfVolume, FileName)) { + AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"Netboot", + BuiltinIcon(BUILTIN_ICON_TOOL_NETBOOT), 'N', FALSE); + } // if + MyFreePool(FileName); + } // while + FileName = NULL; + break; + + case TAG_APPLE_RECOVERY: + FileName = StrDuplicate(L"\\com.apple.recovery.boot\\boot.efi"); + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + if ((Volumes[VolumeIndex]->RootDir != NULL) && (IsValidTool(SelfVolume, FileName))) { + SPrint(Description, 255, L"Apple Recovery on %s", Volumes[VolumeIndex]->VolName); + AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, FileName, Description, + BuiltinIcon(BUILTIN_ICON_TOOL_APPLE_RESCUE), 'R', TRUE); + } // if + } // for + MyFreePool(FileName); + FileName = NULL; + break; + + case TAG_WINDOWS_RECOVERY: + j = 0; + while ((FileName = FindCommaDelimited(GlobalConfig.WindowsRecoveryFiles, j++)) != NULL) { + SplitVolumeAndFilename(&FileName, &VolName); + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + if ((Volumes[VolumeIndex]->RootDir != NULL) && + (IsValidTool(SelfVolume, FileName)) && + ((VolName == NULL) || MyStriCmp(VolName, Volumes[VolumeIndex]->VolName))) { + SPrint(Description, 255, L"Microsoft Recovery on %s", Volumes[VolumeIndex]->VolName); + AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, FileName, Description, + BuiltinIcon(BUILTIN_ICON_TOOL_WINDOWS_RESCUE), 'R', TRUE); + } // if + } // for + } // while + MyFreePool(FileName); + FileName = NULL; + MyFreePool(VolName); + VolName = NULL; + break; + + case TAG_MOK_TOOL: + FindTool(MokLocations, MOK_NAMES, L"MOK utility", BUILTIN_ICON_TOOL_MOK_TOOL); + break; + + case TAG_FWUPDATE_TOOL: + FindTool(MokLocations, FWUPDATE_NAMES, L"firmware update utility", BUILTIN_ICON_TOOL_FWUPDATE); + break; + + case TAG_CSR_ROTATE: + if ((GetCsrStatus(&CsrValue) == EFI_SUCCESS) && (GlobalConfig.CsrValues)) { + TempMenuEntry = CopyMenuEntry(&MenuEntryRotateCsr); + TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_CSR_ROTATE); + AddMenuEntry(&MainMenu, TempMenuEntry); + } // if + break; + + case TAG_MEMTEST: + FindTool(MEMTEST_LOCATIONS, MEMTEST_NAMES, L"Memory test utility", BUILTIN_ICON_TOOL_MEMTEST); + break; + + } // switch() + } // for +} // static VOID ScanForTools + +// Rescan for boot loaders +VOID RescanAll(BOOLEAN DisplayMessage) { + FreeList((VOID ***) &(MainMenu.Entries), &MainMenu.EntryCount); + MainMenu.Entries = NULL; + MainMenu.EntryCount = 0; + ConnectAllDriversToAllControllers(); + ScanVolumes(); + ReadConfig(GlobalConfig.ConfigFilename); + SetVolumeIcons(); + ScanForBootloaders(TRUE); + ScanForTools(); +} // VOID RescanAll() + +#ifdef __MAKEWITH_TIANO + +// Minimal initialization function +static VOID InitializeLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { + gST = SystemTable; + // gImageHandle = ImageHandle; + gBS = SystemTable->BootServices; + // gRS = SystemTable->RuntimeServices; + gRT = SystemTable->RuntimeServices; // Some BDS functions need gRT to be set + EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS); +} + +#endif + +// Set up our own Secure Boot extensions.... +// Returns TRUE on success, FALSE otherwise +static BOOLEAN SecureBootSetup(VOID) { + EFI_STATUS Status; + BOOLEAN Success = FALSE; + + if (secure_mode() && ShimLoaded()) { + Status = security_policy_install(); + if (Status == EFI_SUCCESS) { + Success = TRUE; + } else { + Print(L"Failed to install MOK Secure Boot extensions"); + PauseForKey(); + } + } + return Success; +} // VOID SecureBootSetup() + +// Remove our own Secure Boot extensions.... +// Returns TRUE on success, FALSE otherwise +static BOOLEAN SecureBootUninstall(VOID) { + EFI_STATUS Status; + BOOLEAN Success = TRUE; + + if (secure_mode()) { + Status = security_policy_uninstall(); + if (Status != EFI_SUCCESS) { + Success = FALSE; + BeginTextScreen(L"Secure Boot Policy Failure"); + Print(L"Failed to uninstall MOK Secure Boot extensions; forcing a reboot."); + PauseForKey(); + refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } + return Success; +} // VOID SecureBootUninstall + +// Sets the global configuration filename; will be CONFIG_FILE_NAME unless the +// "-c" command-line option is set, in which case that takes precedence. +// If an error is encountered, leaves the value alone (it should be set to +// CONFIG_FILE_NAME when GlobalConfig is initialized). +static VOID SetConfigFilename(EFI_HANDLE ImageHandle) { + EFI_LOADED_IMAGE *Info; + CHAR16 *Options, *FileName, *SubString; + EFI_STATUS Status; + + Status = refit_call3_wrapper(BS->HandleProtocol, ImageHandle, &LoadedImageProtocol, (VOID **) &Info); + if ((Status == EFI_SUCCESS) && (Info->LoadOptionsSize > 0)) { + Options = (CHAR16 *) Info->LoadOptions; + SubString = MyStrStr(Options, L" -c "); + if (SubString) { + FileName = StrDuplicate(&SubString[4]); + if (FileName) { + LimitStringLength(FileName, 256); + } + + if (FileExists(SelfDir, FileName)) { + GlobalConfig.ConfigFilename = FileName; + } else { + Print(L"Specified configuration file (%s) doesn't exist; using\n'refind.conf' default\n", FileName); + MyFreePool(FileName); + } // if/else + } // if + } // if +} // VOID SetConfigFilename() + +// +// main entry point +// +EFI_STATUS +EFIAPI +efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status; + BOOLEAN MainLoopRunning = TRUE; + BOOLEAN MokProtocol; + REFIT_MENU_ENTRY *ChosenEntry; + UINTN MenuExit, i; + CHAR16 *SelectionName = NULL; + EG_PIXEL BGColor = COLOR_LIGHTBLUE; + + // bootstrap + InitializeLib(ImageHandle, SystemTable); + Status = InitRefitLib(ImageHandle); + if (EFI_ERROR(Status)) + return Status; + + // read configuration + CopyMem(GlobalConfig.ScanFor, "ieom ", NUM_SCAN_OPTIONS); + FindLegacyBootType(); + if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC) + CopyMem(GlobalConfig.ScanFor, "ihebocm ", NUM_SCAN_OPTIONS); + SetConfigFilename(ImageHandle); + MokProtocol = SecureBootSetup(); + LoadDrivers(); + ScanVolumes(); // Do before ReadConfig() because it needs SelfVolume->VolName + ReadConfig(GlobalConfig.ConfigFilename); + SetVolumeIcons(); + + if (GlobalConfig.SpoofOSXVersion && GlobalConfig.SpoofOSXVersion[0] != L'\0') + SetAppleOSInfo(); + + InitScreen(); + WarnIfLegacyProblems(); + MainMenu.TimeoutSeconds = GlobalConfig.Timeout; + + // disable EFI watchdog timer + refit_call4_wrapper(BS->SetWatchdogTimer, 0x0000, 0x0000, 0x0000, NULL); + + // further bootstrap (now with config available) + SetupScreen(); +<<<<<<< HEAD + ScanForBootloaders(GlobalConfig.ScanDelay == 0); + ScanForTools(); + // SetupScreen() clears the screen; but ScanForBootloaders() may display a + // message that must be deleted, so do so + BltClearScreen(TRUE); +======= + pdInitialize(); +>>>>>>> d63734581c19715b3dc13ab89c520def8d5c4566 + + if (GlobalConfig.ScanDelay > 0) { + if (GlobalConfig.ScanDelay > 1) + egDisplayMessage(L"Pausing before disk scan; please wait....", &BGColor, CENTER); + for (i = 0; i < GlobalConfig.ScanDelay; i++) + refit_call1_wrapper(BS->Stall, 1000000); + BltClearScreen(TRUE); + RescanAll(GlobalConfig.ScanDelay > 1); + } // if + + if (GlobalConfig.DefaultSelection) + SelectionName = StrDuplicate(GlobalConfig.DefaultSelection); + + while (MainLoopRunning) { + MenuExit = RunMainMenu(&MainMenu, &SelectionName, &ChosenEntry); + + // The Escape key triggers a re-scan operation.... + if (MenuExit == MENU_EXIT_ESCAPE) { + MenuExit = 0; + RescanAll(TRUE); + continue; + } + + switch (ChosenEntry->Tag) { + + case TAG_REBOOT: // Reboot + TerminateScreen(); + refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL); + MainLoopRunning = FALSE; // just in case we get this far + break; + + case TAG_SHUTDOWN: // Shut Down + TerminateScreen(); + refit_call4_wrapper(RT->ResetSystem, EfiResetShutdown, EFI_SUCCESS, 0, NULL); + MainLoopRunning = FALSE; // just in case we get this far + break; + + case TAG_ABOUT: // About rEFInd + AboutrEFInd(); + break; + + case TAG_LOADER: // Boot OS via .EFI loader + StartLoader((LOADER_ENTRY *)ChosenEntry, SelectionName); + break; + + case TAG_LEGACY: // Boot legacy OS + StartLegacy((LEGACY_ENTRY *)ChosenEntry, SelectionName); + break; + + case TAG_LEGACY_UEFI: // Boot a legacy OS on a non-Mac + StartLegacyUEFI((LEGACY_ENTRY *)ChosenEntry, SelectionName); + break; + + case TAG_TOOL: // Start a EFI tool + StartTool((LOADER_ENTRY *)ChosenEntry); + break; + + case TAG_HIDDEN: // Manage hidden tag entries + ManageHiddenTags(); + break; + + case TAG_EXIT: // Terminate rEFInd + if ((MokProtocol) && !SecureBootUninstall()) { + MainLoopRunning = FALSE; // just in case we get this far + } else { + BeginTextScreen(L" "); + return EFI_SUCCESS; + } + break; + + case TAG_FIRMWARE: // Reboot into firmware's user interface + RebootIntoFirmware(); + break; + + case TAG_CSR_ROTATE: + RotateCsrValue(); + break; + + } // switch() + } // while() + + // If we end up here, things have gone wrong. Try to reboot, and if that + // fails, go into an endless loop. + refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL); + EndlessIdleLoop(); + + return EFI_SUCCESS; +} /* efi_main() */ diff -Nru refind-0.10.4/refind/Makefile refind-0.11.2/refind/Makefile --- refind-0.10.4/refind/Makefile 2015-12-06 21:22:32.000000000 +0000 +++ refind-0.11.2/refind/Makefile 2017-08-05 23:11:59.000000000 +0000 @@ -36,7 +36,7 @@ -L$(SRCDIR)/../EfiLib/ LOCAL_LIBS = -leg -lmok -lEfiLib -OBJS = main.o mystrings.o apple.o line_edit.o config.o menu.o \ +OBJS = main.o mystrings.o apple.o line_edit.o config.o menu.o pointer.o \ screen.o icns.o gpt.o crc32.o lib.o driver_support.o \ legacy.o diff -Nru refind-0.10.4/refind/Make.tiano refind-0.11.2/refind/Make.tiano --- refind-0.10.4/refind/Make.tiano 2015-12-06 21:16:56.000000000 +0000 +++ refind-0.11.2/refind/Make.tiano 2017-08-05 23:11:59.000000000 +0000 @@ -12,7 +12,7 @@ include ../Make.common -EFILIB = $(EDK2BASE)/Build/Mde/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH)/MdePkg/Library +EFILIB = $(TIANOBASE)/Build/Mde/$(TARGET)_$(TOOL_CHAIN_TAG)/$(UC_ARCH)/MdePkg/Library ALL_EFILIBS = $(EFILIB)/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib/OUTPUT/BaseDebugPrintErrorLevelLib.lib \ $(EFILIB)/BasePrintLib/BasePrintLib/OUTPUT/BasePrintLib.lib \ $(EFILIB)/BasePcdLibNull/BasePcdLibNull/OUTPUT/BasePcdLibNull.lib \ @@ -36,7 +36,7 @@ endif SOURCE_NAMES = apple config mystrings line_edit driver_support icns \ - lib main menu screen gpt crc32 legacy AutoGen + lib main menu pointer screen gpt crc32 legacy AutoGen OBJS = $(SOURCE_NAMES:=.obj) all: $(BUILDME) diff -Nru refind-0.10.4/refind/menu.c refind-0.11.2/refind/menu.c --- refind-0.10.4/refind/menu.c 2016-10-03 18:39:24.000000000 +0000 +++ refind-0.11.2/refind/menu.c 2017-10-09 17:42:20.000000000 +0000 @@ -34,7 +34,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Modifications copyright (c) 2012-2015 Roderick W. Smith + * Modifications copyright (c) 2012-2017 Roderick W. Smith * * Modifications distributed under the terms of the GNU General Public * License (GPL) version 3 (GPLv3), or (at your option) any later version. @@ -64,6 +64,7 @@ #include "libegint.h" #include "line_edit.h" #include "mystrings.h" +#include "icns.h" #include "../include/refit_call_wrapper.h" #include "../include/egemb_back_selected_small.h" @@ -100,11 +101,18 @@ static EG_IMAGE *SelectionImages[2] = { NULL, NULL }; static EG_PIXEL SelectionBackgroundPixel = { 0xff, 0xff, 0xff, 0 }; -//Touch variables -EFI_ABSOLUTE_POINTER_PROTOCOL *TouchProtocol = NULL; -EFI_GUID TouchGuid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID; -BOOLEAN TouchEnabled = FALSE; -BOOLEAN TouchActive = FALSE; +EFI_EVENT* WaitList = NULL; +UINTN WaitListLength = 0; + +// Pointer variables +BOOLEAN PointerEnabled = FALSE; +BOOLEAN PointerActive = FALSE; +BOOLEAN DrawSelection = TRUE; + +extern EFI_GUID RefindGuid; +extern REFIT_MENU_ENTRY MenuEntryReturn; +static REFIT_MENU_ENTRY MenuEntryYes = { L"Yes", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryNo = { L"No", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL }; // // Graphics helper functions @@ -305,72 +313,67 @@ } -static INTN FindMenuShortcutEntry(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *Defaults) -{ - UINTN i, j = 0; +static INTN FindMenuShortcutEntry(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *Defaults) { + UINTN i, j = 0, ShortcutLength; CHAR16 *Shortcut; while ((Shortcut = FindCommaDelimited(Defaults, j)) != NULL) { - if (StrLen(Shortcut) == 1) { - if (Shortcut[0] >= 'a' && Shortcut[0] <= 'z') - Shortcut[0] -= ('a' - 'A'); - if (Shortcut[0]) { + ShortcutLength = StrLen(Shortcut); + if (ShortcutLength == 1) { + if (Shortcut[0] >= 'a' && Shortcut[0] <= 'z') + Shortcut[0] -= ('a' - 'A'); + if (Shortcut[0]) { + for (i = 0; i < Screen->EntryCount; i++) { + if (Screen->Entries[i]->ShortcutDigit == Shortcut[0] || Screen->Entries[i]->ShortcutLetter == Shortcut[0]) { + MyFreePool(Shortcut); + return i; + } // if + } // for + } // if + } else if (ShortcutLength > 1) { for (i = 0; i < Screen->EntryCount; i++) { - if (Screen->Entries[i]->ShortcutDigit == Shortcut[0] || Screen->Entries[i]->ShortcutLetter == Shortcut[0]) { - MyFreePool(Shortcut); - return i; - } // if + if (StriSubCmp(Shortcut, Screen->Entries[i]->Title)) { + MyFreePool(Shortcut); + return i; + } // if } // for - } // if - } else if (StrLen(Shortcut) > 1) { - for (i = 0; i < Screen->EntryCount; i++) { - if (StriSubCmp(Shortcut, Screen->Entries[i]->Title)) { - MyFreePool(Shortcut); - return i; - } // if - } // for - } - MyFreePool(Shortcut); - j++; + } + MyFreePool(Shortcut); + j++; } // while() return -1; -} +} // static INTN FindMenuShortcutEntry() // Identify the end of row 0 and the beginning of row 1; store the results in the // appropriate fields in State. Also reduce MaxVisible if that value is greater // than the total number of row-0 tags and if we're in an icon-based screen static VOID IdentifyRows(IN SCROLL_STATE *State, IN REFIT_MENU_SCREEN *Screen) { - UINTN i; + UINTN i; - State->FinalRow0 = 0; - State->InitialRow1 = State->MaxIndex; - for (i = 0; i <= State->MaxIndex; i++) { - if (Screen->Entries[i]->Row == 0) { - State->FinalRow0 = i; - } else if ((Screen->Entries[i]->Row == 1) && (State->InitialRow1 > i)) { - State->InitialRow1 = i; - } // if/else - } // for - if ((State->ScrollMode == SCROLL_MODE_ICONS) && (State->MaxVisible > (State->FinalRow0 + 1))) - State->MaxVisible = State->FinalRow0 + 1; + State->FinalRow0 = 0; + State->InitialRow1 = State->MaxIndex; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0) { + State->FinalRow0 = i; + } else if ((Screen->Entries[i]->Row == 1) && (State->InitialRow1 > i)) { + State->InitialRow1 = i; + } // if/else + } // for + if ((State->ScrollMode == SCROLL_MODE_ICONS) && (State->MaxVisible > (State->FinalRow0 + 1))) + State->MaxVisible = State->FinalRow0 + 1; } // static VOID IdentifyRows() -// Blank the screen, wait for a keypress or touch event, and restore banner/background. +// Blank the screen, wait for a keypress or pointer event, and restore banner/background. // Screen may still require redrawing of text and icons on return. // TODO: Support more sophisticated screen savers, such as power-saving // mode and dynamic images. static VOID SaveScreen(VOID) { - UINTN index; EG_PIXEL Black = { 0x0, 0x0, 0x0, 0 }; - EFI_EVENT WaitList[2] = { ST->ConIn->WaitForKey, NULL }; egClearScreen(&Black); - if(TouchEnabled) { - WaitList[1] = TouchProtocol->WaitForInput; - refit_call3_wrapper(BS->WaitForEvent, 2, WaitList, &index); - } else { - refit_call3_wrapper(BS->WaitForEvent, 1, WaitList, &index); - } + + WaitForInput(0); + if (AllowGraphicsMode) SwitchToGraphicsAndClear(); ReadAllKeyStrokes(); @@ -385,7 +388,6 @@ SCROLL_STATE State; EFI_STATUS Status; EFI_INPUT_KEY key; - UINTN index; INTN ShortcutEntry; BOOLEAN HaveTimeout = FALSE; BOOLEAN WaitForRelease = FALSE; @@ -394,9 +396,8 @@ CHAR16 TimeoutMessage[256]; CHAR16 KeyAsString[2]; UINTN MenuExit; - - EFI_STATUS TouchStatus = EFI_NOT_READY; - EFI_ABSOLUTE_POINTER_STATE *TouchState = NULL; + EFI_STATUS PointerStatus = EFI_NOT_READY; + UINTN Item; if (Screen->TimeoutSeconds > 0) { HaveTimeout = TRUE; @@ -436,6 +437,7 @@ while (!MenuExit) { // update the screen + pdClear(); if (State.PaintAll && (GlobalConfig.ScreensaverTime != -1)) { StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_ALL, NULL); State.PaintAll = FALSE; @@ -443,6 +445,7 @@ StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_SELECTION, NULL); State.PaintSelection = FALSE; } + pdDraw(); if (WaitForRelease) { Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key); @@ -467,77 +470,54 @@ } } - // read key press or touch event (and wait for them if applicable) - if(TouchEnabled) { - TouchStatus = refit_call2_wrapper(TouchProtocol->GetState, TouchProtocol, TouchState); + // read key press or pointer event (and wait for them if applicable) + if (PointerEnabled) { + PointerStatus = pdUpdateState(); } Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key); - if(Status == EFI_SUCCESS) { - TouchActive = FALSE; + if (Status == EFI_SUCCESS) { + PointerActive = FALSE; + DrawSelection = TRUE; TimeSinceKeystroke = 0; - } else if (TouchStatus == EFI_SUCCESS) { - if (StyleFunc != MainMenuStyle) { + } else if (PointerStatus == EFI_SUCCESS) { + if (StyleFunc != MainMenuStyle && pdGetState().Press) { // prevent user from getting stuck on submenus // (the only one currently reachable without a keyboard is the about screen) MenuExit = MENU_EXIT_ENTER; break; } - TouchActive = TRUE; + PointerActive = TRUE; TimeSinceKeystroke = 0; } else { - EFI_EVENT WaitList[3] = { ST->ConIn->WaitForKey, NULL, NULL }; if (HaveTimeout && TimeoutCountdown == 0) { // timeout expired MenuExit = MENU_EXIT_TIMEOUT; break; } else if (HaveTimeout || GlobalConfig.ScreensaverTime > 0) { - EFI_EVENT TimerEvent; - UINTN ElapsCount = 1; + UINTN ElapsCount = 1; - Status = refit_call5_wrapper(BS->CreateEvent, EVT_TIMER, 0, NULL, NULL, &TimerEvent); - if (EFI_ERROR(Status)) { - refit_call1_wrapper(BS->Stall, 100000); // Pause for 100 ms - } else { - UINTN Index; - - refit_call3_wrapper(BS->SetTimer, TimerEvent, TimerRelative, 10000000); // 1s Timeout - - if (TouchEnabled) { - WaitList[1] = TouchProtocol->WaitForInput; - WaitList[2] = TimerEvent; - Status = refit_call3_wrapper(BS->WaitForEvent, 3, WaitList, &Index); - } else { - WaitList[1] = TimerEvent; - Status = refit_call3_wrapper(BS->WaitForEvent, 2, WaitList, &Index); - } + UINTN Input = WaitForInput(1000); // 1s Timeout - refit_call1_wrapper(BS->CloseEvent, TimerEvent); - if (EFI_ERROR(Status)) - refit_call1_wrapper(BS->Stall, 100000); // Pause for 100 ms - else if(Index == 0 || (TouchEnabled && Index == 1)) - continue; - else - ElapsCount = 10; // always counted as 1s to end of the timeout + if (Input == INPUT_KEY || Input == INPUT_POINTER) { + continue; + } else if (Input == INPUT_TIMEOUT) { + ElapsCount = 10; // always counted as 1s to end of the timeout } + TimeSinceKeystroke += ElapsCount; - if(HaveTimeout) { + if (HaveTimeout) { TimeoutCountdown = TimeoutCountdown <= ElapsCount ? 0 : TimeoutCountdown - ElapsCount; } else if (GlobalConfig.ScreensaverTime > 0 && - TimeSinceKeystroke > (GlobalConfig.ScreensaverTime * 10)) + TimeSinceKeystroke > (GlobalConfig.ScreensaverTime * 10)) { - SaveScreen(); - State.PaintAll = TRUE; - TimeSinceKeystroke = 0; + SaveScreen(); + State.PaintAll = TRUE; + TimeSinceKeystroke = 0; } // if } else { - if (TouchEnabled) { - WaitList[1] = TouchProtocol->WaitForInput; - refit_call3_wrapper(BS->WaitForEvent, 2, WaitList, &index); - } else { - refit_call3_wrapper(BS->WaitForEvent, 1, WaitList, &index); - } + WaitForInput(0); } continue; } // if/else !read keystroke @@ -553,7 +533,7 @@ } } - if(!TouchActive) { // react to key press + if (!PointerActive) { // react to key press switch (key.ScanCode) { case SCAN_UP: UpdateScroll(&State, SCROLL_LINE_UP); @@ -586,6 +566,9 @@ case SCAN_F2: MenuExit = MENU_EXIT_DETAILS; break; + case SCAN_DELETE: + MenuExit = MENU_EXIT_HIDE; + break; case SCAN_F10: egScreenShot(); break; @@ -600,9 +583,16 @@ case ' ': MenuExit = MENU_EXIT_ENTER; break; + case CHAR_BACKSPACE: + MenuExit = MENU_EXIT_ESCAPE; + break; case '+': + case CHAR_TAB: MenuExit = MENU_EXIT_DETAILS; break; + case '-': + MenuExit = MENU_EXIT_HIDE; + break; default: KeyAsString[0] = key.UnicodeChar; KeyAsString[1] = 0; @@ -613,26 +603,53 @@ } break; } - } else { //react to touch event - UINTN Item = FindMainMenuItem(Screen, &State, TouchState->CurrentX, TouchState->CurrentY); + } else { //react to pointer event + if (StyleFunc != MainMenuStyle) { + continue; // nothing to find on submenus + } + State.PreviousSelection = State.CurrentSelection; + POINTER_STATE PointerState = pdGetState(); + Item = FindMainMenuItem(Screen, &State, PointerState.X, PointerState.Y); switch (Item) { - case TOUCH_NO_ITEM: - //do nothing + case POINTER_NO_ITEM: + if(DrawSelection) { + DrawSelection = FALSE; + State.PaintSelection = TRUE; + } break; - case TOUCH_LEFT_ARROW: - UpdateScroll(&State, SCROLL_PAGE_UP); + case POINTER_LEFT_ARROW: + if(PointerState.Press) { + UpdateScroll(&State, SCROLL_PAGE_UP); + } + if(DrawSelection) { + DrawSelection = FALSE; + State.PaintSelection = TRUE; + } break; - case TOUCH_RIGHT_ARROW: - UpdateScroll(&State, SCROLL_PAGE_DOWN); + case POINTER_RIGHT_ARROW: + if(PointerState.Press) { + UpdateScroll(&State, SCROLL_PAGE_DOWN); + } + if(DrawSelection) { + DrawSelection = FALSE; + State.PaintSelection = TRUE; + } break; default: - State.CurrentSelection = Item; - MenuExit = MENU_EXIT_ENTER; + if (!DrawSelection || Item != State.CurrentSelection) { + DrawSelection = TRUE; + State.PaintSelection = TRUE; + State.CurrentSelection = Item; + } + if(PointerState.Press) { + MenuExit = MENU_EXIT_ENTER; + } break; } } } + pdClear(); StyleFunc(Screen, &State, MENU_FUNCTION_CLEANUP, NULL); if (ChosenEntry) @@ -1030,8 +1047,8 @@ { EG_IMAGE *Background; - // don't draw selection image if using touch - if (selected && !TouchActive) { + // if using pointer, don't draw selection image when not hovering + if (selected && DrawSelection) { Background = egCropImage(GlobalConfig.ScreenBackground, XPos, YPos, SelectionImages[Entry->Row]->Width, SelectionImages[Entry->Row]->Height); egComposeImage(Background, SelectionImages[Entry->Row], 0, 0); @@ -1058,11 +1075,13 @@ DrawMainMenuEntry(Screen->Entries[i], (i == State->CurrentSelection) ? TRUE : FALSE, itemPosX[i], row1PosY); } } - if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL)) { + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL) && (!PointerActive || (PointerActive && DrawSelection))) { DrawTextWithTransparency(L"", 0, textPosY); DrawTextWithTransparency(Screen->Entries[State->CurrentSelection]->Title, (UGAWidth - egComputeTextWidth(Screen->Entries[State->CurrentSelection]->Title)) >> 1, textPosY); + } else { + DrawTextWithTransparency(L"", 0, textPosY); } if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) { @@ -1096,11 +1115,13 @@ } // if/else DrawMainMenuEntry(Screen->Entries[State->PreviousSelection], FALSE, itemPosX[XSelectPrev], YPosPrev); DrawMainMenuEntry(Screen->Entries[State->CurrentSelection], TRUE, itemPosX[XSelectCur], YPosCur); - if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL)) { + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL) && (!PointerActive || (PointerActive && DrawSelection))) { DrawTextWithTransparency(L"", 0, textPosY); DrawTextWithTransparency(Screen->Entries[State->CurrentSelection]->Title, (UGAWidth - egComputeTextWidth(Screen->Entries[State->CurrentSelection]->Title)) >> 1, textPosY); + } else { + DrawTextWithTransparency(L"", 0, textPosY); } } else { // Current selection not visible; must redraw the menu.... MainMenuStyle(Screen, State, MENU_FUNCTION_PAINT_ALL, NULL); @@ -1243,82 +1264,129 @@ } // VOID MainMenuStyle() // Determines the index of the main menu item at the given coordinates. -UINTN FindMainMenuItem(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT64 PosX, IN UINT64 PosY) +UINTN FindMainMenuItem(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN PosX, IN UINTN PosY) { - UINTN i; + UINTN i; static UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders; UINTN row0Count, row1Count, row1PosX, row1PosXRunning; static UINTN *itemPosX; static UINTN row0PosY; - UINTN itemRow; + UINTN itemRow; - row0Count = 0; - row1Count = 0; - row0Loaders = 0; - for (i = 0; i <= State->MaxIndex; i++) { - if (Screen->Entries[i]->Row == 1) { - row1Count++; - } else { - row0Loaders++; - if (row0Count < State->MaxVisible) - row0Count++; - } - } - row0PosX = (UGAWidth + TILE_XSPACING - (TileSizes[0] + TILE_XSPACING) * row0Count) >> 1; - row0PosY = ComputeRow0PosY(); - row1PosX = (UGAWidth + TILE_XSPACING - (TileSizes[1] + TILE_XSPACING) * row1Count) >> 1; - row1PosY = row0PosY + TileSizes[0] + TILE_YSPACING; - - if(PosY >= row0PosY && PosY <= row0PosY + TileSizes[0]) { - itemRow = 0; - if(PosX <= row0PosX) { - return TOUCH_LEFT_ARROW; - } - else if(PosX >= (UGAWidth - row0PosX)) { - return TOUCH_RIGHT_ARROW; - } - } else if(PosY >= row1PosY && PosY <= row1PosY + TileSizes[1]) { - itemRow = 1; - } else { // Y coordinate is outside of either row - return TOUCH_NO_ITEM; - } - - UINTN ItemIndex = TOUCH_NO_ITEM; - - itemPosX = AllocatePool(sizeof(UINTN) * Screen->EntryCount); - row0PosXRunning = row0PosX; - row1PosXRunning = row1PosX; - for (i = 0; i <= State->MaxIndex; i++) { - if (Screen->Entries[i]->Row == 0) { - itemPosX[i] = row0PosXRunning; - row0PosXRunning += TileSizes[0] + TILE_XSPACING; - } else { - itemPosX[i] = row1PosXRunning; - row1PosXRunning += TileSizes[1] + TILE_XSPACING; - } - } - - for (i = State->FirstVisible; i <= State->MaxIndex; i++) { - if (Screen->Entries[i]->Row == 0 && itemRow == 0) { - if (i <= State->LastVisible) { - if(PosX >= itemPosX[i - State->FirstVisible] && PosX <= itemPosX[i - State->FirstVisible] + TileSizes[0]) { - ItemIndex = i; - break; - } - } // if - } else if (Screen->Entries[i]->Row == 1 && itemRow == 1) { - if(PosX >= itemPosX[i] && PosX <= itemPosX[i] + TileSizes[1]) { - ItemIndex = i; - break; - } - } - } - - MyFreePool(itemPosX); - - return ItemIndex; + row0Count = 0; + row1Count = 0; + row0Loaders = 0; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 1) { + row1Count++; + } else { + row0Loaders++; + if (row0Count < State->MaxVisible) + row0Count++; + } + } + row0PosX = (UGAWidth + TILE_XSPACING - (TileSizes[0] + TILE_XSPACING) * row0Count) >> 1; + row0PosY = ComputeRow0PosY(); + row1PosX = (UGAWidth + TILE_XSPACING - (TileSizes[1] + TILE_XSPACING) * row1Count) >> 1; + row1PosY = row0PosY + TileSizes[0] + TILE_YSPACING; + + if (PosY >= row0PosY && PosY <= row0PosY + TileSizes[0]) { + itemRow = 0; + if(PosX <= row0PosX) { + return POINTER_LEFT_ARROW; + } + else if(PosX >= (UGAWidth - row0PosX)) { + return POINTER_RIGHT_ARROW; + } + } else if (PosY >= row1PosY && PosY <= row1PosY + TileSizes[1]) { + itemRow = 1; + } else { // Y coordinate is outside of either row + return POINTER_NO_ITEM; + } + + UINTN ItemIndex = POINTER_NO_ITEM; + + itemPosX = AllocatePool(sizeof(UINTN) * Screen->EntryCount); + row0PosXRunning = row0PosX; + row1PosXRunning = row1PosX; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0) { + itemPosX[i] = row0PosXRunning; + row0PosXRunning += TileSizes[0] + TILE_XSPACING; + } else { + itemPosX[i] = row1PosXRunning; + row1PosXRunning += TileSizes[1] + TILE_XSPACING; + } + } + + for (i = State->FirstVisible; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0 && itemRow == 0) { + if (i <= State->LastVisible) { + if(PosX >= itemPosX[i - State->FirstVisible] && PosX <= itemPosX[i - State->FirstVisible] + TileSizes[0]) { + ItemIndex = i; + break; + } + } // if + } else if (Screen->Entries[i]->Row == 1 && itemRow == 1) { + if(PosX >= itemPosX[i] && PosX <= itemPosX[i] + TileSizes[1]) { + ItemIndex = i; + break; + } + } + } + + MyFreePool(itemPosX); + + return ItemIndex; } // VOID FindMainMenuItem() +VOID GenerateWaitList() { + UINTN PointerCount = pdCount(); + WaitListLength = 2 + PointerCount; + + WaitList = AllocatePool(sizeof(EFI_EVENT) * WaitListLength); + + WaitList[0] = ST->ConIn->WaitForKey; + + UINTN Index; + for(Index = 0; Index < PointerCount; Index++) { + WaitList[Index + 1] = pdWaitEvent(Index); + } +} // VOID GenerateWaitList() + +UINTN WaitForInput(UINTN Timeout) { + UINTN Index = INPUT_TIMEOUT; + UINTN Length = WaitListLength; + EFI_EVENT TimerEvent; + EFI_STATUS Status; + + if (Timeout == 0) { + Length--; + } else { + Status = refit_call5_wrapper(BS->CreateEvent, EVT_TIMER, 0, NULL, NULL, &TimerEvent); + if(EFI_ERROR(Status)) { + refit_call1_wrapper(BS->Stall, 100000); // Pause for 100 ms + return INPUT_TIMER_ERROR; + } else { + Status = refit_call3_wrapper(BS->SetTimer, TimerEvent, TimerRelative, Timeout * 10000); + WaitList[Length - 1] = TimerEvent; + } + } + + Status = refit_call3_wrapper(BS->WaitForEvent, Length, WaitList, &Index); + refit_call1_wrapper(BS->CloseEvent, TimerEvent); + + if(EFI_ERROR(Status)) { + refit_call1_wrapper(BS->Stall, 100000); // Pause for 100 ms + return INPUT_TIMER_ERROR; + } else if(Index == 0) { + return INPUT_KEY; + } else if(Index < Length - 1) { + return INPUT_POINTER; + } + return INPUT_TIMEOUT; +} // UINTN WaitForInput() + // Enable the user to edit boot loader options. // Returns TRUE if the user exited with edited options; FALSE if the user // pressed Esc to terminate the edit. @@ -1350,6 +1418,298 @@ // user-callable dispatcher functions // +VOID DisplaySimpleMessage(CHAR16* Title, CHAR16 *Message) { + MENU_STYLE_FUNC Style = TextMenuStyle; + INTN DefaultEntry = 0; + REFIT_MENU_ENTRY *ChosenOption; + REFIT_MENU_SCREEN HideItemMenu = { NULL, NULL, 0, NULL, 0, NULL, 0, NULL, + L"Press Enter to return to main menu", L"" }; + + if (!Message) + return; + + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + HideItemMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); + HideItemMenu.Title = Title; + AddMenuInfoLine(&HideItemMenu, Message); + AddMenuEntry(&HideItemMenu, &MenuEntryReturn); + RunGenericMenu(&HideItemMenu, Style, &DefaultEntry, &ChosenOption); +} // VOID DisplaySimpleMessage() + +// Check each filename in FilenameList to be sure it refers to a valid file. If +// not, delete it. This works only on filenames that are complete, with volume, +// path, and filename components; if the filename omits the volume, the search +// is not done and the item is left intact, no matter what. +// Returns TRUE if any files were deleted, FALSE otherwise. +static BOOLEAN RemoveInvalidFilenames(CHAR16 *FilenameList, CHAR16 *VarName) { + UINTN i = 0; + CHAR16 *Filename, *OneElement, *VolName = NULL /*, *NewList = NULL */; + REFIT_VOLUME *Volume; + EFI_FILE_HANDLE FileHandle; + BOOLEAN DeleteIt = FALSE, DeletedSomething = FALSE; + EFI_STATUS Status; + + while ((OneElement = FindCommaDelimited(FilenameList, i)) != NULL) { + DeleteIt = FALSE; + Filename = StrDuplicate(OneElement); + if (SplitVolumeAndFilename(&Filename, &VolName)) { + DeleteIt = TRUE; + if (FindVolume(&Volume, VolName) && Volume->RootDir) { + Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FileHandle, + Filename, EFI_FILE_MODE_READ, 0); + if (Status == EFI_SUCCESS) { + DeleteIt = FALSE; + refit_call1_wrapper(FileHandle->Close, FileHandle); + } // if file exists + } // if volume exists + } // if list item includes volume + if (DeleteIt) { + DeleteItemFromCsvList(OneElement, FilenameList); + } else { + i++; + } + MyFreePool(OneElement); + MyFreePool(Filename); + MyFreePool(VolName); + DeletedSomething |= DeleteIt; + } // while() + return DeletedSomething; +} // BOOLEAN RemoveInvalidFilenames() + +// Present a menu that enables the user to delete hidden tags (that is, to +// un-hide them). +VOID ManageHiddenTags(VOID) { + CHAR16 *AllTags = NULL, *HiddenTags, *HiddenTools, *HiddenLegacy, *OneElement = NULL; + INTN DefaultEntry = 0; + MENU_STYLE_FUNC Style = TextMenuStyle; + REFIT_MENU_ENTRY *ChosenOption, *MenuEntryItem = NULL; + REFIT_MENU_SCREEN HideItemMenu = { L"Manage Hidden Tags Menu", NULL, 0, NULL, 0, NULL, 0, NULL, + L"Select an option and press Enter or", + L"press Esc to return to main menu without changes" }; + UINTN MenuExit, i = 0; + BOOLEAN SaveTags = FALSE, SaveTools = FALSE, SaveLegacy = FALSE; + EFI_STATUS Status; + + HideItemMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_HIDDEN); + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + + HiddenTags = ReadHiddenTags(L"HiddenTags"); + SaveTags = RemoveInvalidFilenames(HiddenTags, L"HiddenTags"); + if (HiddenTags && (HiddenTags[0] != L'\0')) + AllTags = StrDuplicate(HiddenTags); + HiddenTools = ReadHiddenTags(L"HiddenTools"); + SaveTools = RemoveInvalidFilenames(HiddenTools, L"HiddenTools"); + if (HiddenTools && (HiddenTools[0] != L'\0')) + MergeStrings(&AllTags, HiddenTools, L','); + HiddenLegacy = ReadHiddenTags(L"HiddenLegacy"); + if (HiddenLegacy && (HiddenLegacy[0] != L'\0')) + MergeStrings(&AllTags, HiddenLegacy, L','); + if ((AllTags) && (StrLen(AllTags) > 0)) { + AddMenuInfoLine(&HideItemMenu, L"Select a tag and press Enter to restore it"); + while ((OneElement = FindCommaDelimited(AllTags, i++)) != NULL) { + MenuEntryItem = AllocateZeroPool(sizeof(REFIT_MENU_ENTRY)); + MenuEntryItem->Title = StrDuplicate(OneElement); + MenuEntryItem->Tag = TAG_RETURN; + MenuEntryItem->Row = 1; + AddMenuEntry(&HideItemMenu, MenuEntryItem); + } // while + MenuExit = RunGenericMenu(&HideItemMenu, Style, &DefaultEntry, &ChosenOption); + if (MenuExit == MENU_EXIT_ENTER) { + SaveTags |= DeleteItemFromCsvList(ChosenOption->Title, HiddenTags); + SaveTools |= DeleteItemFromCsvList(ChosenOption->Title, HiddenTools); + if (DeleteItemFromCsvList(ChosenOption->Title, HiddenLegacy)) { + i = HiddenLegacy ? StrLen(HiddenLegacy) : 0; + Status = EfivarSetRaw(&RefindGuid, L"HiddenLegacy", (CHAR8 *) HiddenLegacy, i * 2 + 2 * (i > 0), TRUE); + SaveLegacy = TRUE; + CheckError(Status, L"in ManageHiddenTags()"); + } // if + } // if + if (SaveTags) { + i = HiddenTags ? StrLen(HiddenTags) : 0; + Status = EfivarSetRaw(&RefindGuid, L"HiddenTags", (CHAR8 *) HiddenTags, i * 2 + 2 * (i > 0), TRUE); + CheckError(Status, L"in ManageHiddenTags()"); + } + if (SaveTools) { + i = HiddenTools ? StrLen(HiddenTools) : 0; + Status = EfivarSetRaw(&RefindGuid, L"HiddenTools", (CHAR8 *) HiddenTools, i * 2 + 2 * (i > 0), TRUE); + CheckError(Status, L"in ManageHiddenTags()"); + } + if (SaveTags || SaveTools || SaveLegacy) + RescanAll(TRUE); + } else { + DisplaySimpleMessage(L"Information", L"No hidden tags found"); + } + MyFreePool(AllTags); + MyFreePool(HiddenTags); + MyFreePool(HiddenTools); + MyFreePool(HiddenLegacy); + MyFreePool(OneElement); + MyFreePool(MenuEntryItem); +} // VOID ManageHiddenTags() + +CHAR16* ReadHiddenTags(CHAR16 *VarName) { + CHAR8 *Buffer = NULL; + UINTN Size; + EFI_STATUS Status; + + Status = EfivarGetRaw(&RefindGuid, VarName, &Buffer, &Size); + if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_FOUND)) + CheckError(Status, L"in ReadHiddenTags()"); + if ((Status == EFI_SUCCESS) && (Size == 0)) { + MyFreePool(Buffer); + Buffer = NULL; + } + return (CHAR16 *) Buffer; +} // CHAR16* ReadHiddenTags() + +// Add PathName to the hidden tags variable specified by *VarName. +static VOID AddToHiddenTags(CHAR16 *VarName, CHAR16 *Pathname) { + CHAR16 *HiddenTags; + EFI_STATUS Status; + + if (Pathname && (StrLen(Pathname) > 0)) { + HiddenTags = ReadHiddenTags(VarName); + MergeStrings(&HiddenTags, Pathname, L','); + Status = EfivarSetRaw(&RefindGuid, VarName, (CHAR8 *) HiddenTags, StrLen(HiddenTags) * 2 + 2, TRUE); + CheckError(Status, L"in AddToHiddenTags()"); + MyFreePool(HiddenTags); + } // if +} // VOID AddToHiddenTags() + +// Adds a filename, specified by the *Loader variable, to the *VarName EFI variable, +// using the mostly-prepared *HideItemMenu structure to prompt the user to confirm +// hiding that item. +// Returns TRUE if item was hidden, FALSE otherwise. +static BOOLEAN HideEfiTag(LOADER_ENTRY *Loader, REFIT_MENU_SCREEN *HideItemMenu, CHAR16 *VarName) { + REFIT_VOLUME *TestVolume = NULL; + BOOLEAN TagHidden = FALSE; + CHAR16 *FullPath = NULL, *GuidStr = NULL; + MENU_STYLE_FUNC Style = TextMenuStyle; + UINTN MenuExit; + INTN DefaultEntry = 1; + REFIT_MENU_ENTRY *ChosenOption; + + if ((!Loader) || (!(Loader->Volume)) || (!(Loader->LoaderPath)) || (!HideItemMenu) || (!VarName)) + return FALSE; + + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + + if (Loader->Volume->VolName && (StrLen(Loader->Volume->VolName) > 0)) { + FullPath = StrDuplicate(Loader->Volume->VolName); + } else if (Loader->Volume->PartName && (StrLen(Loader->Volume->PartName) > 0)) { + FullPath = StrDuplicate(Loader->Volume->PartName); + } + MergeStrings(&FullPath, Loader->LoaderPath, L':'); + AddMenuInfoLine(HideItemMenu, PoolPrint(L"Really hide %s?", FullPath)); + AddMenuEntry(HideItemMenu, &MenuEntryYes); + AddMenuEntry(HideItemMenu, &MenuEntryNo); + MenuExit = RunGenericMenu(HideItemMenu, Style, &DefaultEntry, &ChosenOption); + + if (ChosenOption && MyStriCmp(ChosenOption->Title, L"Yes") && (MenuExit == MENU_EXIT_ENTER)) { + GuidStr = GuidAsString(&Loader->Volume->PartGuid); + if (FindVolume(&TestVolume, GuidStr) && TestVolume->RootDir) { + MyFreePool(FullPath); + FullPath = NULL; + MergeStrings(&FullPath, GuidAsString(&Loader->Volume->PartGuid), L'\0'); + MergeStrings(&FullPath, L":", L'\0'); + MergeStrings(&FullPath, Loader->LoaderPath, (Loader->LoaderPath[0] == L'\\' ? L'\0' : L'\\')); + } + AddToHiddenTags(VarName, FullPath); + TagHidden = TRUE; + } // if + + MyFreePool(FullPath); + MyFreePool(GuidStr); + + return TagHidden; +} // BOOLEAN HideEfiTag() + +static BOOLEAN HideLegacyTag(LEGACY_ENTRY *LegacyLoader, REFIT_MENU_SCREEN *HideItemMenu) { + MENU_STYLE_FUNC Style = TextMenuStyle; + REFIT_MENU_ENTRY *ChosenOption; + INTN DefaultEntry = 1; + UINTN MenuExit; + CHAR16 *Name = NULL; + BOOLEAN TagHidden = FALSE; + + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + + if ((GlobalConfig.LegacyType == LEGACY_TYPE_MAC) && LegacyLoader->me.Title) + Name = StrDuplicate(LegacyLoader->me.Title); + if ((GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) && LegacyLoader->BdsOption && LegacyLoader->BdsOption->Description) + Name = StrDuplicate(LegacyLoader->BdsOption->Description); + if (!Name) + Name = StrDuplicate(L"Legacy OS"); + AddMenuInfoLine(HideItemMenu, PoolPrint(L"Really hide '%s'?", Name)); + AddMenuEntry(HideItemMenu, &MenuEntryYes); + AddMenuEntry(HideItemMenu, &MenuEntryNo); + MenuExit = RunGenericMenu(HideItemMenu, Style, &DefaultEntry, &ChosenOption); + if (MyStriCmp(ChosenOption->Title, L"Yes") && (MenuExit == MENU_EXIT_ENTER)) { + AddToHiddenTags(L"HiddenLegacy", Name); + TagHidden = TRUE; + } // if + MyFreePool(Name); + return TagHidden; +} // BOOLEAN HideLegacyTag() + +static VOID HideTag(REFIT_MENU_ENTRY *ChosenEntry) { + LOADER_ENTRY *Loader = (LOADER_ENTRY *) ChosenEntry; + LEGACY_ENTRY *LegacyLoader = (LEGACY_ENTRY *) ChosenEntry; + REFIT_MENU_SCREEN HideItemMenu = { NULL, NULL, 0, NULL, 0, NULL, 0, NULL, + L"Select an option and press Enter or", + L"press Esc to return to main menu without changes" }; + + if (ChosenEntry == NULL) + return; + + HideItemMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_HIDDEN); + // BUG: The RescanAll() calls should be conditional on successful calls to + // HideEfiTag() or HideLegacyTag(); but for the former, this causes + // crashes on a second call hide a tag if the user chose "No" to the first + // call. This seems to be related to memory management of Volumes; the + // crash occurs in FindVolumeAndFilename() and lib.c when calling + // DevicePathToStr(). Calling RescanAll() on all returns from HideEfiTag() + // seems to be an effective workaround, but there's likely a memory + // management bug somewhere that's the root cause. + switch (ChosenEntry->Tag) { + case TAG_LOADER: + if (Loader->DiscoveryType == DISCOVERY_TYPE_AUTO) { + HideItemMenu.Title = L"Hide EFI OS Tag"; + HideEfiTag(Loader, &HideItemMenu, L"HiddenTags"); + RescanAll(TRUE); + } else { + DisplaySimpleMessage(L"Cannot Hide Entry for Manual Boot Stanza", + L"You must edit refind.conf to remove this entry."); + } + break; + case TAG_LEGACY: + case TAG_LEGACY_UEFI: + HideItemMenu.Title = L"Hide Legacy OS Tag"; + if (HideLegacyTag(LegacyLoader, &HideItemMenu)) + RescanAll(TRUE); + break; + case TAG_ABOUT: + case TAG_REBOOT: + case TAG_SHUTDOWN: + case TAG_EXIT: + case TAG_FIRMWARE: + case TAG_CSR_ROTATE: + case TAG_HIDDEN: + DisplaySimpleMessage(L"Unable to Comply", + L"To hide an internal tool, edit the 'showtools' line in refind.conf"); + break; + case TAG_TOOL: + HideItemMenu.Title = L"Hide Tool Tag"; + HideEfiTag(Loader, &HideItemMenu, L"HiddenTools"); + RescanAll(TRUE); + break; + } // switch() +} // VOID HideTag() + UINTN RunMenu(IN REFIT_MENU_SCREEN *Screen, OUT REFIT_MENU_ENTRY **ChosenEntry) { INTN DefaultEntry = -1; @@ -1382,15 +1742,15 @@ if (AllowGraphicsMode) { Style = GraphicsMenuStyle; MainStyle = MainMenuStyle; - if (GlobalConfig.EnableTouch) { - // Check for touch availability - EFI_STATUS status = refit_call3_wrapper(BS->LocateProtocol, &TouchGuid, NULL, (VOID **) &TouchProtocol); - if (status == EFI_SUCCESS) { - TouchEnabled = TouchActive = TRUE; - } - } + + PointerEnabled = PointerActive = pdAvailable(); + DrawSelection = !PointerEnabled; } + // Generate this now and keep it around forever, since it's likely to be + // used after this function terminates.... + GenerateWaitList(); + while (!MenuExit) { MenuExit = RunGenericMenu(Screen, MainStyle, &DefaultEntryIndex, &TempChosenEntry); Screen->TimeoutSeconds = 0; @@ -1409,6 +1769,11 @@ MenuExit = 0; } } // Enter sub-screen + if (MenuExit == MENU_EXIT_HIDE) { + if (GlobalConfig.HiddenTags) + HideTag(TempChosenEntry); + MenuExit = 0; + } // Hide launcher } if (ChosenEntry) diff -Nru refind-0.10.4/refind/menu.c.orig refind-0.11.2/refind/menu.c.orig --- refind-0.10.4/refind/menu.c.orig 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/refind/menu.c.orig 2017-08-04 13:22:55.000000000 +0000 @@ -0,0 +1,1816 @@ +/* + * refit/menu.c + * Menu functions + * + * Copyright (c) 2006 Christoph Pfisterer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Christoph Pfisterer nor the names of the + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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-2017 Roderick W. Smith + * + * Modifications distributed under the terms of the GNU General Public + * License (GPL) version 3 (GPLv3), or (at your option) any later version. + * + */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "global.h" +#include "screen.h" +#include "lib.h" +#include "menu.h" +#include "config.h" +#include "libeg.h" +#include "libegint.h" +#include "line_edit.h" +#include "mystrings.h" +#include "icns.h" +#include "../include/refit_call_wrapper.h" + +#include "../include/egemb_back_selected_small.h" +#include "../include/egemb_back_selected_big.h" +#include "../include/egemb_arrow_left.h" +#include "../include/egemb_arrow_right.h" + +// other menu definitions + +#define MENU_FUNCTION_INIT (0) +#define MENU_FUNCTION_CLEANUP (1) +#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); + +static CHAR16 ArrowUp[2] = { ARROW_UP, 0 }; +static CHAR16 ArrowDown[2] = { ARROW_DOWN, 0 }; +static UINTN TileSizes[2] = { 144, 64 }; + +// Text and icon spacing constants.... +#define TEXT_YMARGIN (2) +#define TITLEICON_SPACING (16) + +#define TILE_XSPACING (8) +#define TILE_YSPACING (16) + +// Alignment values for PaintIcon() +#define ALIGN_RIGHT 1 +#define ALIGN_LEFT 0 + +static EG_IMAGE *SelectionImages[2] = { NULL, NULL }; +static EG_PIXEL SelectionBackgroundPixel = { 0xff, 0xff, 0xff, 0 }; + +EFI_EVENT* WaitList = NULL; +UINTN WaitListLength = 0; + +// Pointer variables +BOOLEAN PointerEnabled = FALSE; +BOOLEAN PointerActive = FALSE; +BOOLEAN DrawSelection = TRUE; + +extern EFI_GUID RefindGuid; +extern REFIT_MENU_ENTRY MenuEntryReturn; +static REFIT_MENU_ENTRY MenuEntryYes = { L"Yes", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL }; +static REFIT_MENU_ENTRY MenuEntryNo = { L"No", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL }; + +// +// Graphics helper functions +// + +static VOID InitSelection(VOID) +{ + EG_IMAGE *TempSmallImage = NULL, *TempBigImage = NULL; + BOOLEAN LoadedSmallImage = FALSE; + + if (!AllowGraphicsMode) + return; + if (SelectionImages[0] != NULL) + return; + + // load small selection image + if (GlobalConfig.SelectionSmallFileName != NULL) { + TempSmallImage = egLoadImage(SelfDir, GlobalConfig.SelectionSmallFileName, TRUE); + } + if (TempSmallImage == NULL) + TempSmallImage = egPrepareEmbeddedImage(&egemb_back_selected_small, TRUE); + else + LoadedSmallImage = TRUE; + SelectionImages[1] = egScaleImage(TempSmallImage, TileSizes[1], TileSizes[1]); + + // load big selection image + if (GlobalConfig.SelectionBigFileName != NULL) { + TempBigImage = egLoadImage(SelfDir, GlobalConfig.SelectionBigFileName, TRUE); + } + if (TempBigImage == NULL) { + if (LoadedSmallImage) { + // calculate big selection image from small one + TempBigImage = egCopyImage(TempSmallImage); + } else { + TempBigImage = egPrepareEmbeddedImage(&egemb_back_selected_big, TRUE); + } + } + SelectionImages[0] = egScaleImage(TempBigImage, TileSizes[0], TileSizes[0]); + + if (TempSmallImage) + egFreeImage(TempSmallImage); + if (TempBigImage) + egFreeImage(TempBigImage); +} // VOID InitSelection() + +// +// Scrolling functions +// + +static VOID InitScroll(OUT SCROLL_STATE *State, IN UINTN ItemCount, IN UINTN VisibleSpace) +{ + State->PreviousSelection = State->CurrentSelection = 0; + State->MaxIndex = (INTN)ItemCount - 1; + State->FirstVisible = 0; + if (AllowGraphicsMode) { + State->MaxVisible = UGAWidth / (TileSizes[0] + TILE_XSPACING) - 1; + } else + State->MaxVisible = ConHeight - 4; + if ((VisibleSpace > 0) && (VisibleSpace < State->MaxVisible)) + State->MaxVisible = (INTN)VisibleSpace; + State->PaintAll = TRUE; + State->PaintSelection = FALSE; + + State->LastVisible = State->FirstVisible + State->MaxVisible - 1; +} + +// Adjust variables relating to the scrolling of tags, for when a selected icon isn't +// visible given the current scrolling condition.... +static VOID AdjustScrollState(IN SCROLL_STATE *State) { + if (State->CurrentSelection > State->LastVisible) { + State->LastVisible = State->CurrentSelection; + State->FirstVisible = 1 + State->CurrentSelection - State->MaxVisible; + if (State->FirstVisible < 0) // shouldn't happen, but just in case.... + State->FirstVisible = 0; + State->PaintAll = TRUE; + } // Scroll forward + if (State->CurrentSelection < State->FirstVisible) { + State->FirstVisible = State->CurrentSelection; + State->LastVisible = State->CurrentSelection + State->MaxVisible - 1; + State->PaintAll = TRUE; + } // Scroll backward +} // static VOID AdjustScrollState + +static VOID UpdateScroll(IN OUT SCROLL_STATE *State, IN UINTN Movement) +{ + State->PreviousSelection = State->CurrentSelection; + + switch (Movement) { + case SCROLL_LINE_LEFT: + if (State->CurrentSelection > 0) { + State->CurrentSelection --; + } + break; + + case SCROLL_LINE_RIGHT: + if (State->CurrentSelection < State->MaxIndex) { + State->CurrentSelection ++; + } + break; + + case SCROLL_LINE_UP: + if (State->ScrollMode == SCROLL_MODE_ICONS) { + if (State->CurrentSelection >= State->InitialRow1) { + if (State->MaxIndex > State->InitialRow1) { // avoid division by 0! + State->CurrentSelection = State->FirstVisible + (State->LastVisible - State->FirstVisible) * + (State->CurrentSelection - State->InitialRow1) / + (State->MaxIndex - State->InitialRow1); + } else { + State->CurrentSelection = State->FirstVisible; + } // if/else + } // if in second row + } else { + if (State->CurrentSelection > 0) + State->CurrentSelection--; + } // if/else + break; + + case SCROLL_LINE_DOWN: + if (State->ScrollMode == SCROLL_MODE_ICONS) { + if (State->CurrentSelection <= State->FinalRow0) { + if (State->LastVisible > State->FirstVisible) { // avoid division by 0! + State->CurrentSelection = State->InitialRow1 + (State->MaxIndex - State->InitialRow1) * + (State->CurrentSelection - State->FirstVisible) / + (State->LastVisible - State->FirstVisible); + } else { + State->CurrentSelection = State->InitialRow1; + } // if/else + } // if in first row + } else { + if (State->CurrentSelection < State->MaxIndex) + State->CurrentSelection++; + } // if/else + break; + + case SCROLL_PAGE_UP: + if (State->CurrentSelection <= State->FinalRow0) + State->CurrentSelection -= State->MaxVisible; + else if (State->CurrentSelection == State->InitialRow1) + State->CurrentSelection = State->FinalRow0; + else + State->CurrentSelection = State->InitialRow1; + if (State->CurrentSelection < 0) + State->CurrentSelection = 0; + break; + + case SCROLL_FIRST: + if (State->CurrentSelection > 0) { + State->PaintAll = TRUE; + State->CurrentSelection = 0; + } + break; + + case SCROLL_PAGE_DOWN: + if (State->CurrentSelection < State->FinalRow0) { + State->CurrentSelection += State->MaxVisible; + if (State->CurrentSelection > State->FinalRow0) + State->CurrentSelection = State->FinalRow0; + } else if (State->CurrentSelection == State->FinalRow0) { + State->CurrentSelection++; + } else { + State->CurrentSelection = State->MaxIndex; + } + if (State->CurrentSelection > State->MaxIndex) + State->CurrentSelection = State->MaxIndex; + break; + + case SCROLL_LAST: + if (State->CurrentSelection < State->MaxIndex) { + State->PaintAll = TRUE; + State->CurrentSelection = State->MaxIndex; + } + break; + + case SCROLL_NONE: + break; + + } + if (State->ScrollMode == SCROLL_MODE_TEXT) + AdjustScrollState(State); + + if (!State->PaintAll && State->CurrentSelection != State->PreviousSelection) + State->PaintSelection = TRUE; + State->LastVisible = State->FirstVisible + State->MaxVisible - 1; +} // static VOID UpdateScroll() + +// +// menu helper functions +// + +VOID AddMenuInfoLine(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *InfoLine) +{ + AddListElement((VOID ***) &(Screen->InfoLines), &(Screen->InfoLineCount), InfoLine); +} + +VOID AddMenuEntry(IN REFIT_MENU_SCREEN *Screen, IN REFIT_MENU_ENTRY *Entry) +{ + AddListElement((VOID ***) &(Screen->Entries), &(Screen->EntryCount), Entry); +} + + +static INTN FindMenuShortcutEntry(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *Defaults) { + UINTN i, j = 0, ShortcutLength; + CHAR16 *Shortcut; + + while ((Shortcut = FindCommaDelimited(Defaults, j)) != NULL) { + ShortcutLength = StrLen(Shortcut); + if (ShortcutLength == 1) { + if (Shortcut[0] >= 'a' && Shortcut[0] <= 'z') + Shortcut[0] -= ('a' - 'A'); + if (Shortcut[0]) { + for (i = 0; i < Screen->EntryCount; i++) { + if (Screen->Entries[i]->ShortcutDigit == Shortcut[0] || Screen->Entries[i]->ShortcutLetter == Shortcut[0]) { + MyFreePool(Shortcut); + return i; + } // if + } // for + } // if + } else if (ShortcutLength > 1) { + for (i = 0; i < Screen->EntryCount; i++) { + if (StriSubCmp(Shortcut, Screen->Entries[i]->Title)) { + MyFreePool(Shortcut); + return i; + } // if + } // for + } + MyFreePool(Shortcut); + j++; + } // while() + return -1; +} // static INTN FindMenuShortcutEntry() + +// Identify the end of row 0 and the beginning of row 1; store the results in the +// appropriate fields in State. Also reduce MaxVisible if that value is greater +// than the total number of row-0 tags and if we're in an icon-based screen +static VOID IdentifyRows(IN SCROLL_STATE *State, IN REFIT_MENU_SCREEN *Screen) { + UINTN i; + + State->FinalRow0 = 0; + State->InitialRow1 = State->MaxIndex; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0) { + State->FinalRow0 = i; + } else if ((Screen->Entries[i]->Row == 1) && (State->InitialRow1 > i)) { + State->InitialRow1 = i; + } // if/else + } // for + if ((State->ScrollMode == SCROLL_MODE_ICONS) && (State->MaxVisible > (State->FinalRow0 + 1))) + State->MaxVisible = State->FinalRow0 + 1; +} // static VOID IdentifyRows() + +// Blank the screen, wait for a keypress or pointer event, and restore banner/background. +// Screen may still require redrawing of text and icons on return. +// TODO: Support more sophisticated screen savers, such as power-saving +// mode and dynamic images. +static VOID SaveScreen(VOID) { + EG_PIXEL Black = { 0x0, 0x0, 0x0, 0 }; + + egClearScreen(&Black); + + WaitForInput(0); + + if (AllowGraphicsMode) + SwitchToGraphicsAndClear(); + ReadAllKeyStrokes(); +} // VOID SaveScreen() + +// +// generic menu function +// +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; + EFI_INPUT_KEY key; + INTN ShortcutEntry; + BOOLEAN HaveTimeout = FALSE; + BOOLEAN WaitForRelease = FALSE; + UINTN TimeoutCountdown = 0; + INTN PreviousTime = -1, CurrentTime, TimeSinceKeystroke = 0; + CHAR16 TimeoutMessage[256]; + CHAR16 KeyAsString[2]; + UINTN MenuExit; + EFI_STATUS PointerStatus = EFI_NOT_READY; + UINTN Item; + + if (Screen->TimeoutSeconds > 0) { + HaveTimeout = TRUE; + TimeoutCountdown = Screen->TimeoutSeconds * 10; + } + MenuExit = 0; + + 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 (GlobalConfig.ScreensaverTime != -1) + UpdateScroll(&State, SCROLL_NONE); + } + + if (Screen->TimeoutSeconds == -1) { + Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key); + if (Status == EFI_NOT_READY) { + MenuExit = MENU_EXIT_TIMEOUT; + } else { + KeyAsString[0] = key.UnicodeChar; + KeyAsString[1] = 0; + ShortcutEntry = FindMenuShortcutEntry(Screen, KeyAsString); + if (ShortcutEntry >= 0) { + State.CurrentSelection = ShortcutEntry; + MenuExit = MENU_EXIT_ENTER; + } else { + WaitForRelease = TRUE; + HaveTimeout = FALSE; + } + } + } + + if (GlobalConfig.ScreensaverTime != -1) + State.PaintAll = TRUE; + + while (!MenuExit) { + // update the screen + pdClear(); + if (State.PaintAll && (GlobalConfig.ScreensaverTime != -1)) { + StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_ALL, NULL); + State.PaintAll = FALSE; + } else if (State.PaintSelection) { + StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_SELECTION, NULL); + State.PaintSelection = FALSE; + } + if(PointerActive) { + pdDraw(); + } + + if (WaitForRelease) { + Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key); + if (Status == EFI_SUCCESS) { + // reset, because otherwise the buffer gets queued with keystrokes + refit_call2_wrapper(ST->ConIn->Reset, ST->ConIn, FALSE); + refit_call1_wrapper(BS->Stall, 100000); + } else { + WaitForRelease = FALSE; + refit_call2_wrapper(ST->ConIn->Reset, ST->ConIn, TRUE); + } + continue; + } + + if (HaveTimeout) { + CurrentTime = (TimeoutCountdown + 5) / 10; + if (CurrentTime != PreviousTime) { + SPrint(TimeoutMessage, 255, L"%s in %d seconds", Screen->TimeoutText, CurrentTime); + if (GlobalConfig.ScreensaverTime != -1) + StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_TIMEOUT, TimeoutMessage); + PreviousTime = CurrentTime; + } + } + +<<<<<<< HEAD + // read key press or touch event (and wait for them if applicable) + if (TouchEnabled) { + TouchStatus = refit_call2_wrapper(TouchProtocol->GetState, TouchProtocol, &TouchState); + } + Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key); + + if (Status == EFI_SUCCESS) { + TouchActive = FALSE; +======= + // read key press or pointer event (and wait for them if applicable) + if(PointerEnabled) { + PointerStatus = pdUpdateState(); + } + Status = refit_call2_wrapper(ST->ConIn->ReadKeyStroke, ST->ConIn, &key); + + if(Status == EFI_SUCCESS) { + PointerActive = FALSE; + DrawSelection = TRUE; +>>>>>>> d63734581c19715b3dc13ab89c520def8d5c4566 + TimeSinceKeystroke = 0; + } else if (PointerStatus == EFI_SUCCESS) { + if (StyleFunc != MainMenuStyle && pdGetState().Press) { + // prevent user from getting stuck on submenus + // (the only one currently reachable without a keyboard is the about screen) + MenuExit = MENU_EXIT_ENTER; + break; + } + + PointerActive = TRUE; + TimeSinceKeystroke = 0; + } else { + if (HaveTimeout && TimeoutCountdown == 0) { + // timeout expired + MenuExit = MENU_EXIT_TIMEOUT; + break; + } else if (HaveTimeout || GlobalConfig.ScreensaverTime > 0) { + UINTN ElapsCount = 1; + + UINTN Input = WaitForInput(1000); // 1s Timeout + + if(Input == INPUT_KEY || Input == INPUT_POINTER) { + continue; + } else if(Input == INPUT_TIMEOUT) { + ElapsCount = 10; // always counted as 1s to end of the timeout + } + + TimeSinceKeystroke += ElapsCount; + if(HaveTimeout) { + TimeoutCountdown = TimeoutCountdown <= ElapsCount ? 0 : TimeoutCountdown - ElapsCount; + } else if (GlobalConfig.ScreensaverTime > 0 && + TimeSinceKeystroke > (GlobalConfig.ScreensaverTime * 10)) + { + SaveScreen(); + State.PaintAll = TRUE; + TimeSinceKeystroke = 0; + } // if + } else { + WaitForInput(0); + } + continue; + } // if/else !read keystroke + + if (HaveTimeout) { + // the user pressed a key, cancel the timeout + StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_TIMEOUT, L""); + HaveTimeout = FALSE; + if (GlobalConfig.ScreensaverTime == -1) { // cancel start-with-blank-screen coding + GlobalConfig.ScreensaverTime = 0; + if (!GlobalConfig.TextOnly) + BltClearScreen(TRUE); + } + } + + if(!PointerActive) { // react to key press + switch (key.ScanCode) { + case SCAN_UP: + UpdateScroll(&State, SCROLL_LINE_UP); + break; + case SCAN_LEFT: + UpdateScroll(&State, SCROLL_LINE_LEFT); + break; + case SCAN_DOWN: + UpdateScroll(&State, SCROLL_LINE_DOWN); + break; + case SCAN_RIGHT: + UpdateScroll(&State, SCROLL_LINE_RIGHT); + break; + case SCAN_HOME: + UpdateScroll(&State, SCROLL_FIRST); + break; + case SCAN_END: + UpdateScroll(&State, SCROLL_LAST); + break; + case SCAN_PAGE_UP: + UpdateScroll(&State, SCROLL_PAGE_UP); + break; + case SCAN_PAGE_DOWN: + UpdateScroll(&State, SCROLL_PAGE_DOWN); + break; + case SCAN_ESC: + MenuExit = MENU_EXIT_ESCAPE; + break; + case SCAN_INSERT: + case SCAN_F2: + MenuExit = MENU_EXIT_DETAILS; + break; + case SCAN_DELETE: + MenuExit = MENU_EXIT_HIDE; + break; + case SCAN_F10: + egScreenShot(); + break; + case 0x0016: // F12 + if (EjectMedia()) + MenuExit = MENU_EXIT_ESCAPE; + break; + } + switch (key.UnicodeChar) { + case CHAR_LINEFEED: + case CHAR_CARRIAGE_RETURN: + case ' ': + MenuExit = MENU_EXIT_ENTER; + break; + case CHAR_BACKSPACE: + MenuExit = MENU_EXIT_ESCAPE; + break; + case '+': + case CHAR_TAB: + MenuExit = MENU_EXIT_DETAILS; + break; + case 'd': + MenuExit = MENU_EXIT_HIDE; + break; + default: + KeyAsString[0] = key.UnicodeChar; + KeyAsString[1] = 0; + ShortcutEntry = FindMenuShortcutEntry(Screen, KeyAsString); + if (ShortcutEntry >= 0) { + State.CurrentSelection = ShortcutEntry; + MenuExit = MENU_EXIT_ENTER; + } + break; + } + } else { //react to pointer event + if (StyleFunc != MainMenuStyle) { + continue; // nothing to find on submenus + } + State.PreviousSelection = State.CurrentSelection; + POINTER_STATE PointerState = pdGetState(); + Item = FindMainMenuItem(Screen, &State, PointerState.X, PointerState.Y); + switch (Item) { + case POINTER_NO_ITEM: + if(DrawSelection) { + DrawSelection = FALSE; + State.PaintSelection = TRUE; + } + break; + case POINTER_LEFT_ARROW: + if(PointerState.Press) { + UpdateScroll(&State, SCROLL_PAGE_UP); + } + if(DrawSelection) { + DrawSelection = FALSE; + State.PaintSelection = TRUE; + } + break; + case POINTER_RIGHT_ARROW: + if(PointerState.Press) { + UpdateScroll(&State, SCROLL_PAGE_DOWN); + } + if(DrawSelection) { + DrawSelection = FALSE; + State.PaintSelection = TRUE; + } + break; + default: + if (!DrawSelection || Item != State.CurrentSelection) { + DrawSelection = TRUE; + State.PaintSelection = TRUE; + State.CurrentSelection = Item; + } + if(PointerState.Press) { + MenuExit = MENU_EXIT_ENTER; + } + break; + } + } + } + + pdClear(); + StyleFunc(Screen, &State, MENU_FUNCTION_CLEANUP, NULL); + + if (ChosenEntry) + *ChosenEntry = Screen->Entries[State.CurrentSelection]; + *DefaultEntryIndex = State.CurrentSelection; + return MenuExit; +} /* static UINTN RunGenericMenu() */ + +// +// text-mode generic style +// + +// Show information lines in text mode. +static VOID ShowTextInfoLines(IN REFIT_MENU_SCREEN *Screen) { + INTN i; + + BeginTextScreen(Screen->Title); + if (Screen->InfoLineCount > 0) { + refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); + for (i = 0; i < (INTN)Screen->InfoLineCount; i++) { + refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, 4 + i); + refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, Screen->InfoLines[i]); + } + } +} // VOID ShowTextInfoLines() + +// Do most of the work for text-based menus.... +static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText) +{ + INTN i; + UINTN MenuWidth, ItemWidth, MenuHeight; + static UINTN MenuPosY; + static CHAR16 **DisplayStrings; + CHAR16 TimeoutMessage[256]; + + State->ScrollMode = SCROLL_MODE_TEXT; + switch (Function) { + + case MENU_FUNCTION_INIT: + // vertical layout + MenuPosY = 4; + if (Screen->InfoLineCount > 0) + MenuPosY += Screen->InfoLineCount + 1; + MenuHeight = ConHeight - MenuPosY - 3; + if (Screen->TimeoutSeconds > 0) + MenuHeight -= 2; + InitScroll(State, Screen->EntryCount, MenuHeight); + + // determine width of the menu + MenuWidth = 20; // minimum + for (i = 0; i <= State->MaxIndex; i++) { + ItemWidth = StrLen(Screen->Entries[i]->Title); + if (MenuWidth < ItemWidth) + MenuWidth = ItemWidth; + } + MenuWidth += 2; + if (MenuWidth > ConWidth - 3) + MenuWidth = ConWidth - 3; + + // prepare strings for display + DisplayStrings = AllocatePool(sizeof(CHAR16 *) * Screen->EntryCount); + for (i = 0; i <= State->MaxIndex; i++) { + // Note: Theoretically, SPrint() is a cleaner way to do this; but the + // description of the StrSize parameter to SPrint implies it's measured + // in characters, but in practice both TianoCore and GNU-EFI seem to + // use bytes instead, resulting in truncated displays. I could just + // double the size of the StrSize parameter, but that seems unsafe in + // case a future library change starts treating this as characters, so + // I'm doing it the hard way in this instance. + // TODO: Review the above and possibly change other uses of SPrint() + DisplayStrings[i] = AllocateZeroPool(2 * sizeof(CHAR16)); + DisplayStrings[i][0] = L' '; + MergeStrings(&DisplayStrings[i], Screen->Entries[i]->Title, 0); + if (StrLen(DisplayStrings[i]) > MenuWidth) + DisplayStrings[i][MenuWidth - 1] = 0; + // TODO: use more elaborate techniques for shortening too long strings (ellipses in the middle) + // TODO: account for double-width characters + } // for + + break; + + case MENU_FUNCTION_CLEANUP: + // release temporary memory + for (i = 0; i <= State->MaxIndex; i++) + MyFreePool(DisplayStrings[i]); + MyFreePool(DisplayStrings); + break; + + case MENU_FUNCTION_PAINT_ALL: + // paint the whole screen (initially and after scrolling) + + ShowTextInfoLines(Screen); + for (i = 0; i <= State->MaxIndex; i++) { + if (i >= State->FirstVisible && i <= State->LastVisible) { + refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2, MenuPosY + (i - State->FirstVisible)); + if (i == State->CurrentSelection) + refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_CURRENT); + else + refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_BASIC); + refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[i]); + } + } + // scrolling indicators + refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_SCROLLARROW); + refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, MenuPosY); + if (State->FirstVisible > 0) + refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, ArrowUp); + else + refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, L" "); + refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, MenuPosY + State->MaxVisible); + if (State->LastVisible < State->MaxIndex) + 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_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_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_CURRENT); + refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[State->CurrentSelection]); + break; + + case MENU_FUNCTION_PAINT_TIMEOUT: + 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 - 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 - 3); + SPrint(TimeoutMessage, 255, L"%s ", ParamText); + refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, TimeoutMessage); + } + break; + + } +} + +// +// graphical generic style +// + +inline static UINTN TextLineHeight(VOID) { + return egGetFontHeight() + TEXT_YMARGIN * 2; +} // UINTN TextLineHeight() + +// +// Display a submenu +// + +// Display text with a solid background (MenuBackgroundPixel or SelectionBackgroundPixel). +// Indents text by one character and placed TEXT_YMARGIN pixels down from the +// specified XPos and YPos locations. +static VOID DrawText(IN CHAR16 *Text, IN BOOLEAN Selected, IN UINTN FieldWidth, IN UINTN XPos, IN UINTN YPos) +{ + EG_IMAGE *TextBuffer; + EG_PIXEL Bg; + + TextBuffer = egCreateImage(FieldWidth, TextLineHeight(), FALSE); + + egFillImage(TextBuffer, &MenuBackgroundPixel); + Bg = MenuBackgroundPixel; + if (Selected) { + // draw selection bar background + egFillImageArea(TextBuffer, 0, 0, FieldWidth, TextBuffer->Height, &SelectionBackgroundPixel); + Bg = SelectionBackgroundPixel; + } + + // render the text + egRenderText(Text, TextBuffer, egGetFontCellWidth(), TEXT_YMARGIN, (Bg.r + Bg.g + Bg.b) / 3); + egDrawImageWithTransparency(TextBuffer, NULL, XPos, YPos, TextBuffer->Width, TextBuffer->Height); +// BltImage(TextBuffer, XPos, YPos); +} + +// Finds the average brightness of the input Image. +// NOTE: Passing an Image that covers the whole screen can strain the +// capacity of a UINTN on a 32-bit system with a very large display. +// Using UINT64 instead is unworkable, since the code won't compile +// on a 32-bit system. As the intended use for this function is to handle +// a single text string's background, this shouldn't be a problem, but it +// may need addressing if it's applied more broadly.... +static UINT8 AverageBrightness(EG_IMAGE *Image) { + UINTN i; + UINTN Sum = 0; + + 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; +} // UINT8 AverageBrightness() + +// Display text against the screen's background image. Special case: If Text is NULL +// or 0-length, clear the line. Does NOT indent the text or reposition it relative +// to the specified XPos and YPos values. +static VOID DrawTextWithTransparency(IN CHAR16 *Text, IN UINTN XPos, IN UINTN YPos) +{ + UINTN TextWidth; + EG_IMAGE *TextBuffer = NULL; + + if (Text == NULL) + Text = L""; + + egMeasureText(Text, &TextWidth, NULL); + if (TextWidth == 0) { + TextWidth = UGAWidth; + XPos = 0; + } + + TextBuffer = egCropImage(GlobalConfig.ScreenBackground, XPos, YPos, TextWidth, TextLineHeight()); + if (TextBuffer == NULL) + return; + + // render the text + egRenderText(Text, TextBuffer, 0, 0, AverageBrightness(TextBuffer)); + egDrawImageWithTransparency(TextBuffer, NULL, XPos, YPos, TextBuffer->Width, TextBuffer->Height); + egFreeImage(TextBuffer); +} + +// Compute the size & position of the window that will hold a subscreen's information. +static VOID ComputeSubScreenWindowSize(REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN *XPos, UINTN *YPos, + UINTN *Width, UINTN *Height, UINTN *LineWidth) { + UINTN i, ItemWidth, HintTop, BannerBottomEdge, TitleWidth; + UINTN FontCellWidth = egGetFontCellWidth(); + UINTN FontCellHeight = egGetFontHeight(); + + *Width = 20; + *Height = 5; + TitleWidth = egComputeTextWidth(Screen->Title); + + for (i = 0; i < Screen->InfoLineCount; i++) { + ItemWidth = StrLen(Screen->InfoLines[i]); + if (*Width < ItemWidth) { + *Width = ItemWidth; + } + (*Height)++; + } + for (i = 0; i <= State->MaxIndex; i++) { + ItemWidth = StrLen(Screen->Entries[i]->Title); + if (*Width < ItemWidth) { + *Width = ItemWidth; + } + (*Height)++; + } + *Width = (*Width + 2) * FontCellWidth; + *LineWidth = *Width; + if (Screen->TitleImage) + *Width += (Screen->TitleImage->Width + TITLEICON_SPACING * 2 + FontCellWidth); + else + *Width += FontCellWidth; + + if (*Width < TitleWidth) + *Width = TitleWidth + 2 * FontCellWidth; + + // Keep it within the bounds of the screen, or 2/3 of the screen's width + // for screens over 800 pixels wide + if (*Width > UGAWidth) + *Width = UGAWidth; + + *XPos = (UGAWidth - *Width) / 2; + + HintTop = UGAHeight - (FontCellHeight * 3); // top of hint text + *Height *= TextLineHeight(); + if (Screen->TitleImage && (*Height < (Screen->TitleImage->Height + TextLineHeight() * 4))) + *Height = Screen->TitleImage->Height + TextLineHeight() * 4; + + if (GlobalConfig.BannerBottomEdge >= HintTop) { // probably a full-screen image; treat it as an empty banner + BannerBottomEdge = 0; + } else { + BannerBottomEdge = GlobalConfig.BannerBottomEdge; + } + if (*Height > (HintTop - BannerBottomEdge - FontCellHeight * 2)) { + BannerBottomEdge = 0; + } + if (*Height > (HintTop - BannerBottomEdge - FontCellHeight * 2)) { + // TODO: Implement scrolling in text screen. + *Height = (HintTop - BannerBottomEdge - FontCellHeight * 2); + } + + *YPos = ((UGAHeight - *Height) / 2); + if (*YPos < BannerBottomEdge) + *YPos = BannerBottomEdge + FontCellHeight + (HintTop - BannerBottomEdge - *Height) / 2; +} // VOID ComputeSubScreenWindowSize() + +// Displays sub-menus +static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText) +{ + INTN i; + UINTN ItemWidth; + static UINTN LineWidth, MenuWidth, MenuHeight, EntriesPosX, TitlePosX, EntriesPosY, TimeoutPosY, CharWidth; + EG_IMAGE *Window; + EG_PIXEL *BackgroundPixel = &(GlobalConfig.ScreenBackground->PixelData[0]); + + CharWidth = egGetFontCellWidth(); + State->ScrollMode = SCROLL_MODE_TEXT; + switch (Function) { + + case MENU_FUNCTION_INIT: + InitScroll(State, Screen->EntryCount, 0); + ComputeSubScreenWindowSize(Screen, State, &EntriesPosX, &EntriesPosY, &MenuWidth, &MenuHeight, &LineWidth); + TimeoutPosY = EntriesPosY + (Screen->EntryCount + 1) * TextLineHeight(); + + // initial painting + SwitchToGraphicsAndClear(); + Window = egCreateFilledImage(MenuWidth, MenuHeight, FALSE, BackgroundPixel); + egDrawImage(Window, EntriesPosX, EntriesPosY); + ItemWidth = egComputeTextWidth(Screen->Title); + if (MenuWidth > ItemWidth) { + TitlePosX = EntriesPosX + (MenuWidth - ItemWidth) / 2 - CharWidth; + } else { + TitlePosX = EntriesPosX; + if (CharWidth > 0) { + i = MenuWidth / CharWidth - 2; + if (i > 0) + Screen->Title[i] = 0; + } // if + } // if/else + break; + + case MENU_FUNCTION_CLEANUP: + // nothing to do + break; + + case MENU_FUNCTION_PAINT_ALL: + ComputeSubScreenWindowSize(Screen, State, &EntriesPosX, &EntriesPosY, &MenuWidth, &MenuHeight, &LineWidth); + DrawText(Screen->Title, FALSE, (StrLen(Screen->Title) + 2) * CharWidth, TitlePosX, EntriesPosY += TextLineHeight()); + if (Screen->TitleImage) { + BltImageAlpha(Screen->TitleImage, EntriesPosX + TITLEICON_SPACING, EntriesPosY + TextLineHeight() * 2, + BackgroundPixel); + EntriesPosX += (Screen->TitleImage->Width + TITLEICON_SPACING * 2); + } + EntriesPosY += (TextLineHeight() * 2); + if (Screen->InfoLineCount > 0) { + for (i = 0; i < (INTN)Screen->InfoLineCount; i++) { + DrawText(Screen->InfoLines[i], FALSE, LineWidth, EntriesPosX, EntriesPosY); + EntriesPosY += TextLineHeight(); + } + EntriesPosY += TextLineHeight(); // also add a blank line + } + + for (i = 0; i <= State->MaxIndex; i++) { + DrawText(Screen->Entries[i]->Title, (i == State->CurrentSelection), LineWidth, EntriesPosX, + EntriesPosY + i * TextLineHeight()); + } + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) { + if ((Screen->Hint1 != NULL) && (StrLen(Screen->Hint1) > 0)) + DrawTextWithTransparency(Screen->Hint1, (UGAWidth - egComputeTextWidth(Screen->Hint1)) / 2, + UGAHeight - (egGetFontHeight() * 3)); + if ((Screen->Hint2 != NULL) && (StrLen(Screen->Hint2) > 0)) + DrawTextWithTransparency(Screen->Hint2, (UGAWidth - egComputeTextWidth(Screen->Hint2)) / 2, + UGAHeight - (egGetFontHeight() * 2)); + } // if + break; + + case MENU_FUNCTION_PAINT_SELECTION: + // redraw selection cursor + DrawText(Screen->Entries[State->PreviousSelection]->Title, FALSE, LineWidth, + EntriesPosX, EntriesPosY + State->PreviousSelection * TextLineHeight()); + DrawText(Screen->Entries[State->CurrentSelection]->Title, TRUE, LineWidth, + EntriesPosX, EntriesPosY + State->CurrentSelection * TextLineHeight()); + break; + + case MENU_FUNCTION_PAINT_TIMEOUT: + DrawText(ParamText, FALSE, LineWidth, EntriesPosX, TimeoutPosY); + break; + + } +} // static VOID GraphicsMenuStyle() + +// +// graphical main menu style +// + +static VOID DrawMainMenuEntry(REFIT_MENU_ENTRY *Entry, BOOLEAN selected, UINTN XPos, UINTN YPos) +{ + EG_IMAGE *Background; + + // if using pointer, don't draw selection image when not hovering + if (selected && DrawSelection) { + Background = egCropImage(GlobalConfig.ScreenBackground, XPos, YPos, + SelectionImages[Entry->Row]->Width, SelectionImages[Entry->Row]->Height); + egComposeImage(Background, SelectionImages[Entry->Row], 0, 0); + BltImageCompositeBadge(Background, Entry->Image, Entry->BadgeImage, XPos, YPos); + } else { // Image not selected; copy background + egDrawImageWithTransparency(Entry->Image, Entry->BadgeImage, XPos, YPos, + SelectionImages[Entry->Row]->Width, SelectionImages[Entry->Row]->Height); + } // if/else +} // VOID DrawMainMenuEntry() + +static VOID PaintAll(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN *itemPosX, + UINTN row0PosY, UINTN row1PosY, UINTN textPosY) { + INTN i; + if (Screen->Entries[State->CurrentSelection]->Row == 0) + AdjustScrollState(State); + for (i = State->FirstVisible; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0) { + if (i <= State->LastVisible) { + DrawMainMenuEntry(Screen->Entries[i], (i == State->CurrentSelection) ? TRUE : FALSE, + itemPosX[i - State->FirstVisible], row0PosY); + } // if + } else { + DrawMainMenuEntry(Screen->Entries[i], (i == State->CurrentSelection) ? TRUE : FALSE, itemPosX[i], row1PosY); + } + } + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL) && (!PointerActive || (PointerActive && DrawSelection))) { + DrawTextWithTransparency(L"", 0, textPosY); + DrawTextWithTransparency(Screen->Entries[State->CurrentSelection]->Title, + (UGAWidth - egComputeTextWidth(Screen->Entries[State->CurrentSelection]->Title)) >> 1, + textPosY); + } else { + DrawTextWithTransparency(L"", 0, textPosY); + } + + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) { + DrawTextWithTransparency(Screen->Hint1, (UGAWidth - egComputeTextWidth(Screen->Hint1)) / 2, + UGAHeight - (egGetFontHeight() * 3)); + DrawTextWithTransparency(Screen->Hint2, (UGAWidth - egComputeTextWidth(Screen->Hint2)) / 2, + UGAHeight - (egGetFontHeight() * 2)); + } // if +} // static VOID PaintAll() + +// Move the selection to State->CurrentSelection, adjusting icon row if necessary... +static VOID PaintSelection(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN *itemPosX, + UINTN row0PosY, UINTN row1PosY, UINTN textPosY) { + UINTN XSelectPrev, XSelectCur, YPosPrev, YPosCur; + + if (((State->CurrentSelection <= State->LastVisible) && (State->CurrentSelection >= State->FirstVisible)) || + (State->CurrentSelection >= State->InitialRow1) ) { + if (Screen->Entries[State->PreviousSelection]->Row == 0) { + XSelectPrev = State->PreviousSelection - State->FirstVisible; + YPosPrev = row0PosY; + } else { + XSelectPrev = State->PreviousSelection; + YPosPrev = row1PosY; + } // if/else + if (Screen->Entries[State->CurrentSelection]->Row == 0) { + XSelectCur = State->CurrentSelection - State->FirstVisible; + YPosCur = row0PosY; + } else { + XSelectCur = State->CurrentSelection; + YPosCur = row1PosY; + } // if/else + DrawMainMenuEntry(Screen->Entries[State->PreviousSelection], FALSE, itemPosX[XSelectPrev], YPosPrev); + DrawMainMenuEntry(Screen->Entries[State->CurrentSelection], TRUE, itemPosX[XSelectCur], YPosCur); + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL) && (!PointerActive || (PointerActive && DrawSelection))) { + DrawTextWithTransparency(L"", 0, textPosY); + DrawTextWithTransparency(Screen->Entries[State->CurrentSelection]->Title, + (UGAWidth - egComputeTextWidth(Screen->Entries[State->CurrentSelection]->Title)) >> 1, + textPosY); + } else { + DrawTextWithTransparency(L"", 0, textPosY); + } + } else { // Current selection not visible; must redraw the menu.... + MainMenuStyle(Screen, State, MENU_FUNCTION_PAINT_ALL, NULL); + } +} // static VOID MoveSelection(VOID) + +// Display a 48x48 icon at the specified location. Uses the image specified by +// ExternalFilename if it's available, or BuiltInImage if it's not. The +// Y position is specified as the center value, and so is adjusted by half +// the icon's height. The X position is set along the icon's left +// edge if Alignment == ALIGN_LEFT, and along the right edge if +// Alignment == ALIGN_RIGHT +static VOID PaintIcon(IN EG_EMBEDDED_IMAGE *BuiltInIcon, IN CHAR16 *ExternalFilename, UINTN PosX, UINTN PosY, UINTN Alignment) { + EG_IMAGE *Icon = NULL; + + Icon = egFindIcon(ExternalFilename, GlobalConfig.IconSizes[ICON_SIZE_SMALL]); + if (Icon == NULL) + Icon = egPrepareEmbeddedImage(BuiltInIcon, TRUE); + if (Icon != NULL) { + if (Alignment == ALIGN_RIGHT) + PosX -= Icon->Width; + egDrawImageWithTransparency(Icon, NULL, PosX, PosY - (Icon->Height / 2), Icon->Width, Icon->Height); + } +} // static VOID () + +UINTN ComputeRow0PosY(VOID) { + return ((UGAHeight / 2) - TileSizes[0] / 2); +} // UINTN ComputeRow0PosY() + +// Display (or erase) the arrow icons to the left and right of an icon's row, +// as appropriate. +static VOID PaintArrows(SCROLL_STATE *State, UINTN PosX, UINTN PosY, UINTN row0Loaders) { + EG_IMAGE *TempImage; + UINTN Width, Height, RightX, AdjPosY; + + // NOTE: Assume that left and right arrows are of the same size.... + Width = egemb_arrow_left.Width; + Height = egemb_arrow_left.Height; + RightX = (UGAWidth + (TileSizes[0] + TILE_XSPACING) * State->MaxVisible) / 2 + TILE_XSPACING; + AdjPosY = PosY - (Height / 2); + + // For PaintIcon() calls, the starting Y position is moved to the midpoint + // of the surrounding row; PaintIcon() adjusts this back up by half the + // icon's height to properly center it. + if ((State->FirstVisible > 0) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS))) { + PaintIcon(&egemb_arrow_left, L"arrow_left", PosX, PosY, ALIGN_RIGHT); + } else { + TempImage = egCropImage(GlobalConfig.ScreenBackground, PosX - Width, AdjPosY, Width, Height); + BltImage(TempImage, PosX - Width, AdjPosY); + egFreeImage(TempImage); + } // if/else + + if ((State->LastVisible < (row0Loaders - 1)) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS))) { + PaintIcon(&egemb_arrow_right, L"arrow_right", RightX, PosY, ALIGN_LEFT); + } else { + TempImage = egCropImage(GlobalConfig.ScreenBackground, RightX, AdjPosY, Width, Height); + BltImage(TempImage, RightX, AdjPosY); + egFreeImage(TempImage); + } // if/else +} // VOID PaintArrows() + +// Display main menu in graphics mode +VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText) +{ + INTN i; + static UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders; + UINTN row0Count, row1Count, row1PosX, row1PosXRunning; + static UINTN *itemPosX; + static UINTN row0PosY, textPosY; + + State->ScrollMode = SCROLL_MODE_ICONS; + switch (Function) { + + case MENU_FUNCTION_INIT: + InitScroll(State, Screen->EntryCount, GlobalConfig.MaxTags); + + // layout + row0Count = 0; + row1Count = 0; + row0Loaders = 0; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 1) { + row1Count++; + } else { + row0Loaders++; + if (row0Count < State->MaxVisible) + row0Count++; + } + } + row0PosX = (UGAWidth + TILE_XSPACING - (TileSizes[0] + TILE_XSPACING) * row0Count) >> 1; + row0PosY = ComputeRow0PosY(); + row1PosX = (UGAWidth + TILE_XSPACING - (TileSizes[1] + TILE_XSPACING) * row1Count) >> 1; + row1PosY = row0PosY + TileSizes[0] + TILE_YSPACING; + if (row1Count > 0) + textPosY = row1PosY + TileSizes[1] + TILE_YSPACING; + else + textPosY = row1PosY; + + itemPosX = AllocatePool(sizeof(UINTN) * Screen->EntryCount); + row0PosXRunning = row0PosX; + row1PosXRunning = row1PosX; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0) { + itemPosX[i] = row0PosXRunning; + row0PosXRunning += TileSizes[0] + TILE_XSPACING; + } else { + itemPosX[i] = row1PosXRunning; + row1PosXRunning += TileSizes[1] + TILE_XSPACING; + } + } + // initial painting + InitSelection(); + SwitchToGraphicsAndClear(); + break; + + case MENU_FUNCTION_CLEANUP: + MyFreePool(itemPosX); + break; + + case MENU_FUNCTION_PAINT_ALL: + PaintAll(Screen, State, itemPosX, row0PosY, row1PosY, textPosY); + // For PaintArrows(), the starting Y position is moved to the midpoint + // of the surrounding row; PaintIcon() adjusts this back up by half the + // icon's height to properly center it. + PaintArrows(State, row0PosX - TILE_XSPACING, row0PosY + (TileSizes[0] / 2), row0Loaders); + break; + + case MENU_FUNCTION_PAINT_SELECTION: + PaintSelection(Screen, State, itemPosX, row0PosY, row1PosY, textPosY); + break; + + case MENU_FUNCTION_PAINT_TIMEOUT: + if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL)) { + DrawTextWithTransparency(L"", 0, textPosY + TextLineHeight()); + DrawTextWithTransparency(ParamText, (UGAWidth - egComputeTextWidth(ParamText)) >> 1, textPosY + TextLineHeight()); + } + break; + + } +} // VOID MainMenuStyle() + +// Determines the index of the main menu item at the given coordinates. +UINTN FindMainMenuItem(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN PosX, IN UINTN PosY) +{ + UINTN i; + static UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders; + UINTN row0Count, row1Count, row1PosX, row1PosXRunning; + static UINTN *itemPosX; + static UINTN row0PosY; +<<<<<<< HEAD + UINTN itemRow; + + row0Count = 0; + row1Count = 0; + row0Loaders = 0; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 1) { + row1Count++; + } else { + row0Loaders++; + if (row0Count < State->MaxVisible) + row0Count++; + } + } + row0PosX = (UGAWidth + TILE_XSPACING - (TileSizes[0] + TILE_XSPACING) * row0Count) >> 1; + row0PosY = ComputeRow0PosY(); + row1PosX = (UGAWidth + TILE_XSPACING - (TileSizes[1] + TILE_XSPACING) * row1Count) >> 1; + row1PosY = row0PosY + TileSizes[0] + TILE_YSPACING; + + if (PosY >= row0PosY && PosY <= row0PosY + TileSizes[0]) { + itemRow = 0; + if (PosX <= row0PosX) { + return TOUCH_LEFT_ARROW; + } else if (PosX >= (UGAWidth - row0PosX)) { + return TOUCH_RIGHT_ARROW; + } + + } else if (PosY >= row1PosY && PosY <= row1PosY + TileSizes[1]) { + itemRow = 1; + + } else { // Y coordinate is outside of either row + return TOUCH_NO_ITEM; + } + + UINTN ItemIndex = TOUCH_NO_ITEM; + + itemPosX = AllocatePool(sizeof(UINTN) * Screen->EntryCount); + row0PosXRunning = row0PosX; + row1PosXRunning = row1PosX; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0) { + itemPosX[i] = row0PosXRunning; + row0PosXRunning += TileSizes[0] + TILE_XSPACING; + } else { + itemPosX[i] = row1PosXRunning; + row1PosXRunning += TileSizes[1] + TILE_XSPACING; + } + } + + for (i = State->FirstVisible; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0 && itemRow == 0) { + if (i <= State->LastVisible) { + if(PosX >= itemPosX[i - State->FirstVisible] && PosX <= itemPosX[i - State->FirstVisible] + TileSizes[0]) { + ItemIndex = i; + break; + } + } // if + } else if (Screen->Entries[i]->Row == 1 && itemRow == 1) { + if (PosX >= itemPosX[i] && PosX <= itemPosX[i] + TileSizes[1]) { + ItemIndex = i; + break; + } + } + } + MyFreePool(itemPosX); + return ItemIndex; +======= + UINTN itemRow; + + row0Count = 0; + row1Count = 0; + row0Loaders = 0; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 1) { + row1Count++; + } else { + row0Loaders++; + if (row0Count < State->MaxVisible) + row0Count++; + } + } + row0PosX = (UGAWidth + TILE_XSPACING - (TileSizes[0] + TILE_XSPACING) * row0Count) >> 1; + row0PosY = ComputeRow0PosY(); + row1PosX = (UGAWidth + TILE_XSPACING - (TileSizes[1] + TILE_XSPACING) * row1Count) >> 1; + row1PosY = row0PosY + TileSizes[0] + TILE_YSPACING; + + if(PosY >= row0PosY && PosY <= row0PosY + TileSizes[0]) { + itemRow = 0; + if(PosX <= row0PosX) { + return POINTER_LEFT_ARROW; + } + else if(PosX >= (UGAWidth - row0PosX)) { + return POINTER_RIGHT_ARROW; + } + } else if(PosY >= row1PosY && PosY <= row1PosY + TileSizes[1]) { + itemRow = 1; + } else { // Y coordinate is outside of either row + return POINTER_NO_ITEM; + } + + UINTN ItemIndex = POINTER_NO_ITEM; + + itemPosX = AllocatePool(sizeof(UINTN) * Screen->EntryCount); + row0PosXRunning = row0PosX; + row1PosXRunning = row1PosX; + for (i = 0; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0) { + itemPosX[i] = row0PosXRunning; + row0PosXRunning += TileSizes[0] + TILE_XSPACING; + } else { + itemPosX[i] = row1PosXRunning; + row1PosXRunning += TileSizes[1] + TILE_XSPACING; + } + } + + for (i = State->FirstVisible; i <= State->MaxIndex; i++) { + if (Screen->Entries[i]->Row == 0 && itemRow == 0) { + if (i <= State->LastVisible) { + if(PosX >= itemPosX[i - State->FirstVisible] && PosX <= itemPosX[i - State->FirstVisible] + TileSizes[0]) { + ItemIndex = i; + break; + } + } // if + } else if (Screen->Entries[i]->Row == 1 && itemRow == 1) { + if(PosX >= itemPosX[i] && PosX <= itemPosX[i] + TileSizes[1]) { + ItemIndex = i; + break; + } + } + } + + MyFreePool(itemPosX); + + return ItemIndex; +>>>>>>> d63734581c19715b3dc13ab89c520def8d5c4566 +} // VOID FindMainMenuItem() + +VOID GenerateWaitList() { + UINTN PointerCount = pdCount(); + WaitListLength = 2 + PointerCount; + WaitList = AllocatePool(sizeof(EFI_EVENT) * WaitListLength); + + WaitList[0] = ST->ConIn->WaitForKey; + + UINTN Index; + for(Index = 0; Index < PointerCount; Index++) { + WaitList[Index + 1] = pdWaitEvent(Index); + } +} // VOID GenerateWaitList() + +UINTN WaitForInput(UINTN Timeout) { + UINTN Index = INPUT_TIMEOUT; + UINTN Length = WaitListLength; + EFI_EVENT TimerEvent; + EFI_STATUS Status; + + if(Timeout == 0) { + Length--; + } else { + Status = refit_call5_wrapper(BS->CreateEvent, EVT_TIMER, 0, NULL, NULL, &TimerEvent); + if(EFI_ERROR(Status)) { + refit_call1_wrapper(BS->Stall, 100000); // Pause for 100 ms + return INPUT_TIMER_ERROR; + } else { + Status = refit_call3_wrapper(BS->SetTimer, TimerEvent, TimerRelative, Timeout * 10000); + WaitList[Length - 1] = TimerEvent; + } + } + + Status = refit_call3_wrapper(BS->WaitForEvent, Length, WaitList, &Index); + refit_call1_wrapper(BS->CloseEvent, TimerEvent); + + if(EFI_ERROR(Status)) { + refit_call1_wrapper(BS->Stall, 100000); // Pause for 100 ms + return INPUT_TIMER_ERROR; + } else if(Index == 0) { + return INPUT_KEY; + } else if(Index < Length - 1) { + return INPUT_POINTER; + } + return INPUT_TIMEOUT; +} // UINTN WaitForInput() + +// Enable the user to edit boot loader options. +// Returns TRUE if the user exited with edited options; FALSE if the user +// pressed Esc to terminate the edit. +static BOOLEAN EditOptions(LOADER_ENTRY *MenuEntry) { + UINTN x_max, y_max; + CHAR16 *EditedOptions; + 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); + + if (line_edit(MenuEntry->LoadOptions, &EditedOptions, x_max)) { + MyFreePool(MenuEntry->LoadOptions); + MenuEntry->LoadOptions = EditedOptions; + retval = TRUE; + } // if + if (!GlobalConfig.TextOnly) + SwitchToGraphics(); + return retval; +} // VOID EditOptions() + +// +// user-callable dispatcher functions +// + +VOID DisplaySimpleMessage(CHAR16* Title, CHAR16 *Message) { + MENU_STYLE_FUNC Style = TextMenuStyle; + INTN DefaultEntry = 0; + REFIT_MENU_ENTRY *ChosenOption; + REFIT_MENU_SCREEN HideItemMenu = { NULL, NULL, 0, NULL, 0, NULL, 0, NULL, + L"Press Enter to return to main menu", L"" }; + + if (!Message) + return; + + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + HideItemMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); + HideItemMenu.Title = Title; + AddMenuInfoLine(&HideItemMenu, Message); + AddMenuEntry(&HideItemMenu, &MenuEntryReturn); + RunGenericMenu(&HideItemMenu, Style, &DefaultEntry, &ChosenOption); +} // VOID DisplaySimpleMessage() + +static BOOLEAN DeleteTagFromVar(CHAR16 *ToDelete, CHAR16 *TagList, CHAR16 *VarName) { + UINTN i = 0; + CHAR16 *OneElement, *NewList = NULL; + BOOLEAN DeletedSomething = FALSE; + EFI_STATUS Status; + + if ((ToDelete == NULL) || (TagList == NULL) || (VarName == NULL)) + return FALSE; + + while ((OneElement = FindCommaDelimited(TagList, i++)) != NULL) { + if (!MyStriCmp(OneElement, ToDelete)) { + MergeStrings(&NewList, OneElement, L','); + } else { + DeletedSomething = TRUE; + } + } // while + MyFreePool(OneElement); + i = StrLen(NewList); + if ((i > 0) && (NewList[i - 1] == L',')) { + NewList[i - 1] = '\0'; + i--; + } // if + if (DeletedSomething) { + if (i == 0) { + Status = EfivarSetRaw(&RefindGuid, VarName, (CHAR8 *) NewList, 0, TRUE); + } else { + Status = EfivarSetRaw(&RefindGuid, VarName, (CHAR8 *) NewList, i * 2 + 2, TRUE); + } // if/else + CheckError(Status, L"in DeleteTagFromVar()"); + } // if + MyFreePool(NewList); + return DeletedSomething; +} // BOOLEAN DeleteTagFromVar() + +// Present a menu that enables the user to delete hidden tags (that is, to +// un-hide them). +VOID ManageHiddenTags(VOID) { + CHAR16 *AllTags = NULL, *HiddenTags, *HiddenTools, *HiddenLegacy, *OneElement = NULL; + INTN DefaultEntry = 0; + MENU_STYLE_FUNC Style = TextMenuStyle; + REFIT_MENU_ENTRY *ChosenOption, *MenuEntryItem; + REFIT_MENU_SCREEN HideItemMenu = { L"Manage Hidden Tags Menu", NULL, 0, NULL, 0, NULL, 0, NULL, + L"Select an option and press Enter or", + L"press Esc to return to main menu without changes" }; + UINTN MenuExit, i = 0; + + HideItemMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_HIDDEN); + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + + HiddenTags = ReadHiddenTags(L"HiddenTags"); + if (HiddenTags && (HiddenTags[0] != L'\0')) + AllTags = StrDuplicate(HiddenTags); + HiddenTools = ReadHiddenTags(L"HiddenTools"); + if (HiddenTools && (HiddenTools[0] != L'\0')) + MergeStrings(&AllTags, HiddenTools, L','); + HiddenLegacy = ReadHiddenTags(L"HiddenLegacy"); + if (HiddenLegacy && (HiddenLegacy[0] != L'\0')) + MergeStrings(&AllTags, HiddenLegacy, L','); + if ((AllTags) && (StrLen(AllTags) > 0)) { + AddMenuInfoLine(&HideItemMenu, L"Select a tag and press Enter to restore it"); + while ((OneElement = FindCommaDelimited(AllTags, i++)) != NULL) { + MenuEntryItem = AllocateZeroPool(sizeof(REFIT_MENU_ENTRY)); + MenuEntryItem->Title = StrDuplicate(OneElement); + MenuEntryItem->Tag = TAG_RETURN; + MenuEntryItem->Row = 1; + AddMenuEntry(&HideItemMenu, MenuEntryItem); + } // while + MenuExit = RunGenericMenu(&HideItemMenu, Style, &DefaultEntry, &ChosenOption); + if (MenuExit == MENU_EXIT_ENTER) { + if (DeleteTagFromVar(ChosenOption->Title, HiddenTags, L"HiddenTags") || + DeleteTagFromVar(ChosenOption->Title, HiddenTools, L"HiddenTools") || + DeleteTagFromVar(ChosenOption->Title, HiddenLegacy, L"HiddenLegacy")) { + RescanAll(TRUE); + } // if + } // if + } else { + DisplaySimpleMessage(L"Information", L"No hidden tags found"); + } + MyFreePool(AllTags); + MyFreePool(HiddenTags); + MyFreePool(HiddenTools); + MyFreePool(HiddenLegacy); + MyFreePool(OneElement); +} // VOID ManageHiddenTags() + +CHAR16* ReadHiddenTags(CHAR16 *VarName) { + CHAR8 *Buffer = NULL; + UINTN Size; + EFI_STATUS Status; + + Status = EfivarGetRaw(&RefindGuid, VarName, &Buffer, &Size); + if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_FOUND)) + CheckError(Status, L"in ReadHiddenTags()"); + if ((Status == EFI_SUCCESS) && (Size == 0)) { + MyFreePool(Buffer); + Buffer = NULL; + } + return (CHAR16 *) Buffer; +} // CHAR16* ReadHiddenTags() + +static VOID AddToHiddenTags(CHAR16 *VarName, CHAR16 *Pathname) { + CHAR16 *HiddenTags; + EFI_STATUS Status; + + if (Pathname && (StrLen(Pathname) > 0)) { + HiddenTags = ReadHiddenTags(VarName); + MergeStrings(&HiddenTags, Pathname, L','); + Status = EfivarSetRaw(&RefindGuid, VarName, (CHAR8 *) HiddenTags, StrLen(HiddenTags) * 2 + 2, TRUE); + CheckError(Status, L"in AddToHiddenTags()"); + MyFreePool(HiddenTags); + } // if +} // VOID AddToHiddenTags() + +static BOOLEAN HideEfiTag(LOADER_ENTRY *Loader, REFIT_MENU_SCREEN *HideItemMenu, CHAR16 *VarName) { + REFIT_VOLUME *Volume = NULL; + BOOLEAN TagHidden = FALSE; + CHAR16 *Filename = NULL, *FullPath = NULL; + MENU_STYLE_FUNC Style = TextMenuStyle; + UINTN MenuExit; + INTN DefaultEntry = 1; + REFIT_MENU_ENTRY *ChosenOption; + + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + + FindVolumeAndFilename(Loader->DevicePath, &Volume, &Filename); + if (Volume->VolName && (StrLen(Volume->VolName) > 0)) { + FullPath = StrDuplicate(Volume->VolName); + } else if (Volume->PartName && (StrLen(Volume->PartName) > 0)) { + FullPath = StrDuplicate(Volume->PartName); + } + MergeStrings(&FullPath, Filename, L':'); + AddMenuInfoLine(HideItemMenu, PoolPrint(L"Really hide %s?", FullPath)); + AddMenuEntry(HideItemMenu, &MenuEntryYes); + AddMenuEntry(HideItemMenu, &MenuEntryNo); + MenuExit = RunGenericMenu(HideItemMenu, Style, &DefaultEntry, &ChosenOption); + if (MyStriCmp(ChosenOption->Title, L"Yes") && (MenuExit == MENU_EXIT_ENTER)) { + MyFreePool(FullPath); + FullPath = NULL; + MergeStrings(&FullPath, GuidAsString(&Volume->PartGuid), L'\0'); + MergeStrings(&FullPath, L":", L'\0'); + MergeStrings(&FullPath, Filename, (Filename[0] == L'\\' ? L'\0' : L'\\')); + AddToHiddenTags(VarName, FullPath); + TagHidden = TRUE; + } // if + MyFreePool(Volume); + MyFreePool(Filename); + MyFreePool(FullPath); + return TagHidden; +} // BOOLEAN HideEfiTag() + +static BOOLEAN HideLegacyTag(LEGACY_ENTRY *LegacyLoader, REFIT_MENU_SCREEN *HideItemMenu) { + MENU_STYLE_FUNC Style = TextMenuStyle; + REFIT_MENU_ENTRY *ChosenOption; + INTN DefaultEntry = 1; + UINTN MenuExit; + CHAR16 *Name = NULL; + + if (AllowGraphicsMode) + Style = GraphicsMenuStyle; + + if ((GlobalConfig.LegacyType == LEGACY_TYPE_MAC) && LegacyLoader->me.Title) + Name = StrDuplicate(LegacyLoader->me.Title); + if ((GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) && LegacyLoader->BdsOption && LegacyLoader->BdsOption->Description) + Name = StrDuplicate(LegacyLoader->BdsOption->Description); + if (!Name) + Name = StrDuplicate(L"Legacy OS"); + AddMenuInfoLine(HideItemMenu, PoolPrint(L"Really hide '%s'?", Name)); + AddMenuEntry(HideItemMenu, &MenuEntryYes); + AddMenuEntry(HideItemMenu, &MenuEntryNo); + MenuExit = RunGenericMenu(HideItemMenu, Style, &DefaultEntry, &ChosenOption); + if (MyStriCmp(ChosenOption->Title, L"Yes") && (MenuExit == MENU_EXIT_ENTER)) { + AddToHiddenTags(L"HiddenLegacy", Name); + } // if + MyFreePool(Name); + return TRUE; +} // BOOLEAN HideLegacyTag() + +static VOID HideOSTag(REFIT_MENU_ENTRY *ChosenEntry) { + LOADER_ENTRY *Loader = (LOADER_ENTRY *) ChosenEntry; + LEGACY_ENTRY *LegacyLoader = (LEGACY_ENTRY *) ChosenEntry; + REFIT_MENU_SCREEN HideItemMenu = { NULL, NULL, 0, NULL, 0, NULL, 0, NULL, + L"Select an option and press Enter or", + L"press Esc to return to main menu without changes" }; + + HideItemMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_HIDDEN); + switch (ChosenEntry->Tag) { + case TAG_LOADER: + if (Loader->DiscoveryType == DISCOVERY_TYPE_AUTO) { + HideItemMenu.Title = L"Hide EFI OS Tag"; + if (HideEfiTag(Loader, &HideItemMenu, L"HiddenTags")) + RescanAll(TRUE); + } else { + DisplaySimpleMessage(L"Cannot Hide Entry for Manual Boot Stanza", + L"You must edit refind.conf to remove this entry."); + } + break; + case TAG_LEGACY: + case TAG_LEGACY_UEFI: + HideItemMenu.Title = L"Hide Legacy OS Tag"; + if (HideLegacyTag(LegacyLoader, &HideItemMenu)) + RescanAll(TRUE); + break; + case TAG_ABOUT: + case TAG_REBOOT: + case TAG_SHUTDOWN: + case TAG_EXIT: + case TAG_FIRMWARE: + case TAG_CSR_ROTATE: + case TAG_HIDDEN: + DisplaySimpleMessage(L"Unable to Comply", + L"To hide an internal tool, edit the 'showtools' line in refind.conf"); + break; + case TAG_TOOL: + HideItemMenu.Title = L"Hide Tool Tag"; + if (HideEfiTag(Loader, &HideItemMenu, L"HiddenTools")) + RescanAll(TRUE); + break; + } // switch() +} // VOID HideOsTag() + +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, &DefaultEntry, ChosenEntry); +} + +UINTN RunMainMenu(REFIT_MENU_SCREEN *Screen, CHAR16** DefaultSelection, REFIT_MENU_ENTRY **ChosenEntry) +{ + MENU_STYLE_FUNC Style = TextMenuStyle; + MENU_STYLE_FUNC MainStyle = TextMenuStyle; + REFIT_MENU_ENTRY *TempChosenEntry; + CHAR16 *MenuTitle; + UINTN MenuExit = 0; + INTN DefaultEntryIndex = -1; + INTN DefaultSubmenuIndex = -1; + + TileSizes[0] = (GlobalConfig.IconSizes[ICON_SIZE_BIG] * 9) / 8; + TileSizes[1] = (GlobalConfig.IconSizes[ICON_SIZE_SMALL] * 4) / 3; + + if ((DefaultSelection != NULL) && (*DefaultSelection != NULL)) { + // Find a menu entry that includes *DefaultSelection as a substring + DefaultEntryIndex = FindMenuShortcutEntry(Screen, *DefaultSelection); + } + + if (AllowGraphicsMode) { + Style = GraphicsMenuStyle; + MainStyle = MainMenuStyle; + + PointerEnabled = PointerActive = pdAvailable(); + DrawSelection = !PointerEnabled; + } + + GenerateWaitList(); + + while (!MenuExit) { + MenuExit = RunGenericMenu(Screen, MainStyle, &DefaultEntryIndex, &TempChosenEntry); + Screen->TimeoutSeconds = 0; + + MenuTitle = StrDuplicate(TempChosenEntry->Title); + 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 ((MenuExit == MENU_EXIT_HIDE) && (GlobalConfig.HiddenTags)) { + HideOSTag(TempChosenEntry); + MenuExit = 0; + } // Hide launcher + } + + FreePool(WaitList); + WaitList = NULL; + WaitListLength = 0; + + if (ChosenEntry) + *ChosenEntry = TempChosenEntry; + if (DefaultSelection) { + MyFreePool(*DefaultSelection); + *DefaultSelection = MenuTitle; + } // if + return MenuExit; +} /* UINTN RunMainMenu() */ diff -Nru refind-0.10.4/refind/menu.h refind-0.11.2/refind/menu.h --- refind-0.10.4/refind/menu.h 2016-10-03 19:28:07.000000000 +0000 +++ refind-0.11.2/refind/menu.h 2017-08-04 13:13:20.000000000 +0000 @@ -53,12 +53,10 @@ #endif #include "global.h" -#ifndef _EFI_POINT_H -#include "../EfiLib/AbsolutePointer.h" -#endif - #include "libeg.h" +#include "pointer.h" + // // menu module // @@ -68,6 +66,7 @@ #define MENU_EXIT_DETAILS (3) #define MENU_EXIT_TIMEOUT (4) #define MENU_EXIT_EJECT (5) +#define MENU_EXIT_HIDE (6) #define TAG_RETURN (99) @@ -94,9 +93,14 @@ #define SCROLL_MODE_TEXT (0) /* Used in text mode & for GUI submenus */ #define SCROLL_MODE_ICONS (1) /* Used for main GUI menu */ -#define TOUCH_NO_ITEM (-1) -#define TOUCH_LEFT_ARROW (-2) -#define TOUCH_RIGHT_ARROW (-3) +#define POINTER_NO_ITEM (-1) +#define POINTER_LEFT_ARROW (-2) +#define POINTER_RIGHT_ARROW (-3) + +#define INPUT_KEY (0) +#define INPUT_POINTER (1) +#define INPUT_TIMEOUT (2) +#define INPUT_TIMER_ERROR (3) struct _refit_menu_screen; @@ -105,8 +109,13 @@ UINTN ComputeRow0PosY(VOID); VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText); UINTN RunMenu(IN REFIT_MENU_SCREEN *Screen, OUT REFIT_MENU_ENTRY **ChosenEntry); +VOID DisplaySimpleMessage(CHAR16 *Title, CHAR16 *Message); +VOID ManageHiddenTags(VOID); +CHAR16* ReadHiddenTags(CHAR16 *VarName); UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16** DefaultSelection, OUT REFIT_MENU_ENTRY **ChosenEntry); -UINTN FindMainMenuItem(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT64 PosX, IN UINT64 PosY); +UINTN FindMainMenuItem(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN PosX, IN UINTN PosY); +VOID GenerateWaitList(); +UINTN WaitForInput(IN UINTN Timeout); #endif diff -Nru refind-0.10.4/refind/mystrings.c refind-0.11.2/refind/mystrings.c --- refind-0.10.4/refind/mystrings.c 2015-11-29 20:10:58.000000000 +0000 +++ refind-0.11.2/refind/mystrings.c 2017-08-06 16:15:11.000000000 +0000 @@ -26,6 +26,7 @@ #include "mystrings.h" #include "lib.h" +#include "screen.h" BOOLEAN StriSubCmp(IN CHAR16 *SmallStr, IN CHAR16 *BigStr) { BOOLEAN Found = 0, Terminate = 0; @@ -236,16 +237,27 @@ // Returns all the digits in the input string, including intervening // non-digit characters. For instance, if InString is "foo-3.3.4-7.img", -// this function returns "3.3.4-7". If InString contains no digits, -// the return value is NULL. +// this function returns "3.3.4-7". The GlobalConfig.ExtraKernelVersionStrings +// variable specifies extra strings that may be treated as numbers. If +// InString contains no digits or ExtraKernelVersionStrings, the return value +// is NULL. CHAR16 *FindNumbers(IN CHAR16 *InString) { - UINTN i, StartOfElement, EndOfElement = 0, CopyLength; - CHAR16 *Found = NULL; + UINTN i = 0, StartOfElement, EndOfElement = 0, CopyLength; + CHAR16 *Found = NULL, *ExtraFound = NULL, *LookFor; if (InString == NULL) return NULL; StartOfElement = StrLen(InString); + + // Find extra_kernel_version_strings + while ((ExtraFound == NULL) && (LookFor = FindCommaDelimited(GlobalConfig.ExtraKernelVersionStrings, i++))) { + if ((ExtraFound = MyStrStr(InString, LookFor))) { + StartOfElement = ExtraFound - InString; + EndOfElement = StartOfElement + StrLen(LookFor) - 1; + } // if + } // while + // Find start & end of target element for (i = 0; InString[i] != L'\0'; i++) { if ((InString[i] >= L'0') && (InString[i] <= L'9')) { @@ -267,6 +279,19 @@ return (Found); } // CHAR16 *FindNumbers() +// Returns the number of characters that are in common between +// String1 and String2 before they diverge. For instance, if +// String1 is "FooBar" and String2 is "FoodiesBar", this function +// will return "3", since they both start with "Foo". +UINTN NumCharsInCommon(IN CHAR16* String1, IN CHAR16* String2) { + UINTN Count = 0; + if ((String1 == NULL) || (String2 == NULL)) + return 0; + while ((String1[Count] != L'\0') && (String2[Count] != L'\0') && (String1[Count] == String2[Count])) + Count++; + return Count; +} // UINTN NumCharsInCommon() + // Find the #Index element (numbered from 0) in a comma-delimited string // of elements. // Returns the found element, or NULL if Index is out of range or InString @@ -302,6 +327,34 @@ return (FoundString); } // CHAR16 *FindCommaDelimited() +// Delete an individual element from a comma-separated value list. +// This function modifies the original *List string, but not the +// *ToDelete string! +// Returns TRUE if the item was deleted, FALSE otherwise. +BOOLEAN DeleteItemFromCsvList(CHAR16 *ToDelete, CHAR16 *List) { + CHAR16 *Found, *Comma; + + if ((ToDelete == NULL) || (List == NULL)) + return FALSE; + + if ((Found = MyStrStr(List, ToDelete)) != NULL) { + if ((Comma = MyStrStr(Found, L",")) == NULL) { + // Found is final element + if (Found == List) { // Found is ONLY element + List[0] = L'\0'; + } else { // Delete the comma preceding Found.... + Found--; + Found[0] = L'\0'; + } // if/else + } else { // Found is NOT final element + StrCpy(Found, &Comma[1]); + } // if/else + return TRUE; + } else { + return FALSE; + } // if/else +} // BOOLEAN DeleteItemFromCsvList() + // Returns TRUE if SmallString is an element in the comma-delimited List, // FALSE otherwise. Performs comparison case-insensitively. BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List) { @@ -335,6 +388,34 @@ return Found; } // BOOLEAN IsSubstringIn() +// Replace *SearchString in **MainString with *ReplString -- but if *SearchString +// is preceded by "%", instead remove that character. +// Returns TRUE if replacement was done, FALSE otherwise. +BOOLEAN ReplaceSubstring(IN OUT CHAR16 **MainString, IN CHAR16 *SearchString, IN CHAR16 *ReplString) { + BOOLEAN WasReplaced = FALSE; + CHAR16 *FoundSearchString, *NewString, *EndString; + + FoundSearchString = MyStrStr(*MainString, SearchString); + if (FoundSearchString) { + NewString = AllocateZeroPool(sizeof(CHAR16) * StrLen(*MainString)); + if (NewString) { + EndString = &(FoundSearchString[StrLen(SearchString)]); + FoundSearchString[0] = L'\0'; + if ((FoundSearchString > *MainString) && (FoundSearchString[-1] == L'%')) { + FoundSearchString[-1] = L'\0'; + ReplString = SearchString; + } // if + StrCpy(NewString, *MainString); + MergeStrings(&NewString, ReplString, L'\0'); + MergeStrings(&NewString, EndString, L'\0'); + MyFreePool(MainString); + *MainString = NewString; + WasReplaced = TRUE; + } // if + } // if + return WasReplaced; +} // BOOLEAN ReplaceSubstring() + // Returns TRUE if *Input contains nothing but valid hexadecimal characters, // FALSE otherwise. Note that a leading "0x" is NOT acceptable in the input! BOOLEAN IsValidHex(CHAR16 *Input) { @@ -456,3 +537,15 @@ return Guid; } // EFI_GUID StringAsGuid() + +// Delete the STRING_LIST pointed to by *StringList. +VOID DeleteStringList(STRING_LIST *StringList) { + STRING_LIST *Current = StringList, *Previous; + + while (Current != NULL) { + MyFreePool(Current->Value); + Previous = Current; + Current = Current->Next; + MyFreePool(Previous); + } +} // VOID DeleteStringList() diff -Nru refind-0.10.4/refind/mystrings.h refind-0.11.2/refind/mystrings.h --- refind-0.10.4/refind/mystrings.h 2015-11-29 20:10:58.000000000 +0000 +++ refind-0.11.2/refind/mystrings.h 2017-08-06 02:17:51.000000000 +0000 @@ -34,6 +34,11 @@ #endif #include "../EfiLib/GenericBdsLib.h" +typedef struct _string_list { + CHAR16 *Value; + struct _string_list *Next; +} STRING_LIST; + BOOLEAN StriSubCmp(IN CHAR16 *TargetStr, IN CHAR16 *BigStr); BOOLEAN MyStriCmp(IN CONST CHAR16 *String1, IN CONST CHAR16 *String2); CHAR16* MyStrStr (IN CHAR16 *String, IN CHAR16 *StrCharSet); @@ -42,9 +47,12 @@ VOID MergeWords(CHAR16 **MergeTo, CHAR16 *InString, CHAR16 AddChar); BOOLEAN LimitStringLength(CHAR16 *TheString, UINTN Limit); CHAR16 *FindNumbers(IN CHAR16 *InString); +UINTN NumCharsInCommon(IN CHAR16* String1, IN CHAR16* String2); CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index); +BOOLEAN DeleteItemFromCsvList(CHAR16 *ToDelete, CHAR16 *List); BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List); BOOLEAN IsInSubstring(IN CHAR16 *BigString, IN CHAR16 *List); +BOOLEAN ReplaceSubstring(IN OUT CHAR16 **MainString, IN CHAR16 *SearchString, IN CHAR16 *ReplString); BOOLEAN IsValidHex(CHAR16 *Input); UINT64 StrToHex(CHAR16 *Input, UINTN Position, UINTN NumChars); @@ -52,5 +60,6 @@ CHAR16 * GuidAsString(EFI_GUID *GuidData); EFI_GUID StringAsGuid(CHAR16 * InString); +VOID DeleteStringList(STRING_LIST *StringList); #endif \ No newline at end of file diff -Nru refind-0.10.4/refind/pointer.c refind-0.11.2/refind/pointer.c --- refind-0.10.4/refind/pointer.c 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/refind/pointer.c 2017-08-12 02:49:17.000000000 +0000 @@ -0,0 +1,305 @@ +/* + * refind/pointer.c + * Pointer device functions + * + * Copyright (c) 2017 CJ Vaughter + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "pointer.h" +#include "global.h" +#include "screen.h" +#include "icns.h" +#include "../include/refit_call_wrapper.h" + +#ifndef EFI32 +EFI_HANDLE* APointerHandles = NULL; +EFI_ABSOLUTE_POINTER_PROTOCOL** APointerProtocol = NULL; +EFI_GUID APointerGuid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID; +UINTN NumAPointerDevices = 0; + +EFI_HANDLE* SPointerHandles = NULL; +EFI_SIMPLE_POINTER_PROTOCOL** SPointerProtocol = NULL; +EFI_GUID SPointerGuid = EFI_SIMPLE_POINTER_PROTOCOL_GUID; +UINTN NumSPointerDevices = 0; + +BOOLEAN PointerAvailable = FALSE; + +UINTN LastXPos = 0, LastYPos = 0; +EG_IMAGE* MouseImage = NULL; +EG_IMAGE* Background = NULL; +#endif + +POINTER_STATE State; + +//////////////////////////////////////////////////////////////////////////////// +// Initialize all pointer devices +//////////////////////////////////////////////////////////////////////////////// +VOID pdInitialize() { + pdCleanup(); // just in case + +#ifndef EFI32 + if (!(GlobalConfig.EnableMouse || GlobalConfig.EnableTouch)) return; + + // Get all handles that support absolute pointer protocol (usually touchscreens, but sometimes mice) + UINTN NumPointerHandles = 0; + EFI_STATUS handlestatus = refit_call5_wrapper(BS->LocateHandleBuffer, ByProtocol, &APointerGuid, NULL, + &NumPointerHandles, &APointerHandles); + + if (!EFI_ERROR(handlestatus)) { + APointerProtocol = AllocatePool(sizeof(EFI_ABSOLUTE_POINTER_PROTOCOL*) * NumPointerHandles); + UINTN Index; + for(Index = 0; Index < NumPointerHandles; Index++) { + // Open the protocol on the handle + EFI_STATUS status = refit_call6_wrapper(BS->OpenProtocol, APointerHandles[Index], &APointerGuid, + (VOID **) &APointerProtocol[NumAPointerDevices], + SelfImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + if (status == EFI_SUCCESS) { + NumAPointerDevices++; + } + } + } else { + GlobalConfig.EnableTouch = FALSE; + } + + // Get all handles that support simple pointer protocol (mice) + NumPointerHandles = 0; + handlestatus = refit_call5_wrapper(BS->LocateHandleBuffer, ByProtocol, &SPointerGuid, NULL, + &NumPointerHandles, &SPointerHandles); + + if(!EFI_ERROR(handlestatus)) { + SPointerProtocol = AllocatePool(sizeof(EFI_SIMPLE_POINTER_PROTOCOL*) * NumPointerHandles); + UINTN Index; + for(Index = 0; Index < NumPointerHandles; Index++) { + // Open the protocol on the handle + EFI_STATUS status = refit_call6_wrapper(BS->OpenProtocol, SPointerHandles[Index], &SPointerGuid, (VOID **) &SPointerProtocol[NumSPointerDevices], SelfImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + if (status == EFI_SUCCESS) { + NumSPointerDevices++; + } + } + } else { + GlobalConfig.EnableMouse = FALSE; + } + + PointerAvailable = (NumAPointerDevices + NumSPointerDevices > 0); + + // load mouse icon + if (PointerAvailable && GlobalConfig.EnableMouse) { + MouseImage = BuiltinIcon(BUILTIN_ICON_MOUSE); + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Frees allocated memory and closes pointer protocols +//////////////////////////////////////////////////////////////////////////////// +VOID pdCleanup() { +#ifndef EFI32 + PointerAvailable = FALSE; + pdClear(); + + if(APointerHandles) { + UINTN Index; + for(Index = 0; Index < NumAPointerDevices; Index++) { + refit_call4_wrapper(BS->CloseProtocol, APointerHandles[Index], &APointerGuid, SelfImageHandle, NULL); + } + FreePool(APointerHandles); + APointerHandles = NULL; + } + if(APointerProtocol) { + FreePool(APointerProtocol); + APointerProtocol = NULL; + } + if(SPointerHandles) { + UINTN Index; + for(Index = 0; Index < NumSPointerDevices; Index++) { + refit_call4_wrapper(BS->CloseProtocol, SPointerHandles[Index], &SPointerGuid, SelfImageHandle, NULL); + } + FreePool(SPointerHandles); + SPointerHandles = NULL; + } + if(SPointerProtocol) { + FreePool(SPointerProtocol); + SPointerProtocol = NULL; + } + if(MouseImage) { + egFreeImage(MouseImage); + Background = NULL; + } + NumAPointerDevices = 0; + NumSPointerDevices = 0; + + LastXPos = UGAWidth / 2; + LastYPos = UGAHeight / 2; +#endif + + State.X = UGAWidth / 2; + State.Y = UGAHeight / 2; + State.Press = FALSE; + State.Holding = FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// Returns whether or not any pointer devices are available +//////////////////////////////////////////////////////////////////////////////// +BOOLEAN pdAvailable() { +#ifdef EFI32 + return FALSE; +#else + return PointerAvailable; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Returns the number of pointer devices available +//////////////////////////////////////////////////////////////////////////////// +UINTN pdCount() { +#ifdef EFI32 + return 0; +#else + return NumAPointerDevices + NumSPointerDevices; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Returns a pointer device's WaitForInput event +//////////////////////////////////////////////////////////////////////////////// +EFI_EVENT pdWaitEvent(UINTN Index) { +#ifdef EFI32 + return NULL; +#else + if(!PointerAvailable || Index >= NumAPointerDevices + NumSPointerDevices) { + return NULL; + } + + if(Index >= NumAPointerDevices) { + return SPointerProtocol[Index - NumAPointerDevices]->WaitForInput; + } + return APointerProtocol[Index]->WaitForInput; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Gets the current state of all pointer devices and assigns State to +// the first available device's state +//////////////////////////////////////////////////////////////////////////////// +EFI_STATUS pdUpdateState() { +#ifdef EFI32 + return EFI_NOT_READY; +#else + if(!PointerAvailable) { + return EFI_NOT_READY; + } + + EFI_STATUS Status = EFI_NOT_READY; + EFI_ABSOLUTE_POINTER_STATE APointerState; + EFI_SIMPLE_POINTER_STATE SPointerState; + BOOLEAN LastHolding = State.Holding; + + UINTN Index; + for(Index = 0; Index < NumAPointerDevices; Index++) { + EFI_STATUS PointerStatus = refit_call2_wrapper(APointerProtocol[Index]->GetState, APointerProtocol[Index], &APointerState); + // if new state found and we haven't already found a new state + if(!EFI_ERROR(PointerStatus) && EFI_ERROR(Status)) { + Status = EFI_SUCCESS; + State.X = (APointerState.CurrentX * UGAWidth) / APointerProtocol[Index]->Mode->AbsoluteMaxX; + State.Y = (APointerState.CurrentY * UGAHeight) / APointerProtocol[Index]->Mode->AbsoluteMaxY; + State.Holding = (APointerState.ActiveButtons & EFI_ABSP_TouchActive); + } + } + for(Index = 0; Index < NumSPointerDevices; Index++) { + EFI_STATUS PointerStatus = refit_call2_wrapper(SPointerProtocol[Index]->GetState, SPointerProtocol[Index], &SPointerState); + // if new state found and we haven't already found a new state + if(!EFI_ERROR(PointerStatus) && EFI_ERROR(Status)) { + Status = EFI_SUCCESS; + + INT32 TargetX = State.X + SPointerState.RelativeMovementX * GlobalConfig.MouseSpeed / SPointerProtocol[Index]->Mode->ResolutionX; + if(TargetX < 0) { + State.X = 0; + } else if(TargetX >= UGAWidth) { + State.X = UGAWidth - 1; + } else { + State.X = TargetX; + } + + INT32 TargetY = State.Y + SPointerState.RelativeMovementY * GlobalConfig.MouseSpeed / SPointerProtocol[Index]->Mode->ResolutionY; + if(TargetY < 0) { + State.Y = 0; + } else if(TargetY >= UGAHeight) { + State.Y = UGAHeight - 1; + } else { + State.Y = TargetY; + } + + State.Holding = SPointerState.LeftButton; + } + } + + State.Press = (LastHolding && !State.Holding); + + return Status; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Returns the current pointer state +//////////////////////////////////////////////////////////////////////////////// +POINTER_STATE pdGetState() { + return State; +} + +//////////////////////////////////////////////////////////////////////////////// +// Draw the mouse at the current coordinates +//////////////////////////////////////////////////////////////////////////////// +VOID pdDraw() { +#ifndef EFI32 + if(Background) { + egFreeImage(Background); + Background = NULL; + } + if(MouseImage) { + UINTN Width = MouseImage->Width; + UINTN Height = MouseImage->Height; + + if(State.X + Width > UGAWidth) { + Width = UGAWidth - State.X; + } + if(State.Y + Height > UGAHeight) { + Height = UGAHeight - State.Y; + } + + Background = egCopyScreenArea(State.X, State.Y, Width, Height); + if(Background) { + BltImageCompositeBadge(Background, MouseImage, NULL, State.X, State.Y); + } + } + LastXPos = State.X; + LastYPos = State.Y; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Restores the background at the position the mouse was last drawn +//////////////////////////////////////////////////////////////////////////////// +VOID pdClear() { +#ifndef EFI32 + if (Background) { + egDrawImage(Background, LastXPos, LastYPos); + egFreeImage(Background); + Background = NULL; + } +#endif +} diff -Nru refind-0.10.4/refind/pointer.h refind-0.11.2/refind/pointer.h --- refind-0.10.4/refind/pointer.h 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/refind/pointer.h 2017-08-12 02:49:21.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * refind/pointer.h + * pointer device functions header file + * + * Copyright (c) 2017 CJ Vaughter + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __REFIND_POINTERDEVICE_H_ +#define __REFIND_POINTERDEVICE_H_ + +#ifdef __MAKEWITH_GNUEFI +#include "efi.h" +#include "efilib.h" +#else +#include "../include/tiano_includes.h" +#endif + +#ifndef _EFI_POINT_H +#include "../EfiLib/AbsolutePointer.h" +#endif + +typedef struct PointerStateStruct { + UINTN X, Y; + BOOLEAN Press; + BOOLEAN Holding; +} POINTER_STATE; + +VOID pdInitialize(); +VOID pdCleanup(); +BOOLEAN pdAvailable(); +UINTN pdCount(); +EFI_EVENT pdWaitEvent(IN UINTN Index); +EFI_STATUS pdUpdateState(); +POINTER_STATE pdGetState(); + +VOID pdDraw(); +VOID pdClear(); + +#endif + +/* EOF */ diff -Nru refind-0.10.4/refind/screen.c refind-0.11.2/refind/screen.c --- refind-0.10.4/refind/screen.c 2016-01-30 18:45:20.000000000 +0000 +++ refind-0.11.2/refind/screen.c 2017-08-11 21:17:07.000000000 +0000 @@ -61,6 +61,7 @@ #include "libegint.h" #include "lib.h" #include "menu.h" +#include "mystrings.h" #include "../include/refit_call_wrapper.h" #include "../include/egemb_refind_banner.h" @@ -76,6 +77,7 @@ UINTN UGAWidth; UINTN UGAHeight; BOOLEAN AllowGraphicsMode; +BOOLEAN HaveResized = FALSE; EG_PIXEL StdBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 }; EG_PIXEL MenuBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 }; @@ -174,10 +176,16 @@ // switch to text mode if requested AllowGraphicsMode = FALSE; SwitchToText(FALSE); - } else if (AllowGraphicsMode) { // clear screen and show banner // (now we know we'll stay in graphics mode) + if ((UGAWidth >= HIDPI_MIN) && !HaveResized) { + GlobalConfig.IconSizes[ICON_SIZE_BADGE] *= 2; + GlobalConfig.IconSizes[ICON_SIZE_SMALL] *= 2; + GlobalConfig.IconSizes[ICON_SIZE_BIG] *= 2; + GlobalConfig.IconSizes[ICON_SIZE_MOUSE] *= 2; + HaveResized = TRUE; + } // if SwitchToGraphics(); if (GlobalConfig.ScreensaverTime != -1) { BltClearScreen(TRUE); @@ -324,11 +332,30 @@ return GotKeyStrokes; } +// Displays *text without regard to appearances. Used mainly for debugging +// and rare error messages. +// Position code is used only in graphics mode. +// TODO: Improve to handle multi-line text. +VOID PrintUglyText(IN CHAR16 *Text, IN UINTN PositionCode) { + EG_PIXEL BGColor = COLOR_RED; + + if (Text) { + if (AllowGraphicsMode && MyStriCmp(L"Apple", ST->FirmwareVendor) && egIsGraphicsModeEnabled()) { + egDisplayMessage(Text, &BGColor, PositionCode); + GraphicsScreenDirty = TRUE; + } else { // non-Mac or in text mode; a Print() statement will work + Print(Text); + Print(L"\n"); + } // if/else + } // if +} // VOID PrintUglyText() + VOID PauseForKey(VOID) { UINTN index; - Print(L"\n* Hit any key to continue *"); + Print(L"\n"); + PrintUglyText(L"* Hit any key to continue *", BOTTOM); if (ReadAllKeyStrokes()) { // remove buffered key strokes refit_call1_wrapper(BS->Stall, 5000000); // 5 seconds delay @@ -337,8 +364,6 @@ refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &index); ReadAllKeyStrokes(); // empty the buffer to protect the menu - - Print(L"\n"); } // Pause a specified number of seconds @@ -372,71 +397,51 @@ // Error handling // -#ifdef __MAKEWITH_GNUEFI BOOLEAN CheckFatalError(IN EFI_STATUS Status, IN CHAR16 *where) { - CHAR16 ErrorName[64]; + CHAR16 *Temp = NULL; if (!EFI_ERROR(Status)) return FALSE; +#ifdef __MAKEWITH_GNUEFI + CHAR16 ErrorName[64]; StatusToString(ErrorName, Status); + Temp = PoolPrint(L"Fatal Error: %s %s", ErrorName, where); +#else + Temp = PoolPrint(L"Fatal Error: %s %s", Status, where); +#endif refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR); - Print(L"Fatal Error: %s %s\n", ErrorName, where); + PrintUglyText(Temp, NEXTLINE); refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); haveError = TRUE; - - //BS->Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData); + MyFreePool(Temp); return TRUE; -} +} // BOOLEAN CheckFatalError() BOOLEAN CheckError(IN EFI_STATUS Status, IN CHAR16 *where) { - CHAR16 ErrorName[64]; + CHAR16 *Temp = NULL; if (!EFI_ERROR(Status)) return FALSE; +#ifdef __MAKEWITH_GNUEFI + CHAR16 ErrorName[64]; StatusToString(ErrorName, Status); + Temp = PoolPrint(L"Error: %s %s", ErrorName, where); +#else + Temp = PoolPrint(L"Error: %r %s", Status, where); +#endif refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR); - Print(L"Error: %s %s\n", ErrorName, where); + PrintUglyText(Temp, NEXTLINE); refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); haveError = TRUE; + MyFreePool(Temp); return TRUE; -} -#else -BOOLEAN CheckFatalError(IN EFI_STATUS Status, IN CHAR16 *where) -{ -// CHAR16 ErrorName[64]; - - if (!EFI_ERROR(Status)) - return FALSE; - - gST->ConOut->SetAttribute (gST->ConOut, ATTR_ERROR); - Print(L"Fatal Error: %r %s\n", Status, where); - gST->ConOut->SetAttribute (gST->ConOut, ATTR_BASIC); - haveError = TRUE; - - //gBS->Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData); - - return TRUE; -} - -BOOLEAN CheckError(IN EFI_STATUS Status, IN CHAR16 *where) -{ - if (!EFI_ERROR(Status)) - return FALSE; - - gST->ConOut->SetAttribute (gST->ConOut, ATTR_ERROR); - Print(L"Error: %r %s\n", Status, where); - gST->ConOut->SetAttribute (gST->ConOut, ATTR_BASIC); - haveError = TRUE; - - return TRUE; -} -#endif +} // BOOLEAN CheckError() // // Graphics functions diff -Nru refind-0.10.4/refind/screen.h refind-0.11.2/refind/screen.h --- refind-0.10.4/refind/screen.h 2015-11-29 18:54:48.000000000 +0000 +++ refind-0.11.2/refind/screen.h 2017-07-31 16:13:54.000000000 +0000 @@ -66,6 +66,12 @@ //#define FONT_CELL_WIDTH (7) //#define FONT_CELL_HEIGHT (12) +// Codes for text position, used by egDisplayMessage() and PrintUglyText() +#define CENTER 0 +#define BOTTOM 1 +#define TOP 2 +#define NEXTLINE 3 + extern UINTN ConWidth; extern UINTN ConHeight; extern CHAR16 *BlankLine; @@ -93,6 +99,7 @@ #endif VOID EndlessIdleLoop(VOID); BOOLEAN ReadAllKeyStrokes(VOID); +VOID PrintUglyText(IN CHAR16 *Text, UINTN PositionCode); VOID PauseForKey(VOID); VOID PauseSeconds(UINTN Seconds); diff -Nru refind-0.10.4/refind.conf-sample refind-0.11.2/refind.conf-sample --- refind-0.10.4/refind.conf-sample 2016-10-03 19:14:38.000000000 +0000 +++ refind-0.11.2/refind.conf-sample 2017-10-15 13:36:07.000000000 +0000 @@ -23,9 +23,9 @@ # security: # banner - the rEFInd title banner (built-in or loaded via "banner") # 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 -# safemode - remove the submenu option to boot Mac OS X in "safe mode" +# singleuser - remove the submenu options to boot macOS in single-user +# or verbose modes; affects ONLY macOS +# safemode - remove the submenu option to boot macOS in "safe mode" # 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 @@ -145,20 +145,44 @@ # feature may not work for you. If it does work, you should be able # to launch an OS or tool by touching it. In a submenu, touching # anywhere launches the currently-selection item; there is, at present, -# no way to select a specific submenu item. +# no way to select a specific submenu item. This feature is mutually +# exclusive with the enable_mouse feature. If both are uncommented, +# the one read most recently takes precedence. # #enable_touch +# Enable mouse support. If active, this feature enables use of the +# computer's mouse. Note, however, that not all computers' EFIs +# provide the necessary underlying support, so this feature may not +# work for you. If it does work, you should be able to launch an +# OS or tool by clicking it with the mouse pointer. This feature +# is mutually exclusive with the enable_touch feature. If both +# are uncommented, the one read most recently takes precedence. +# +#enable_mouse + +# Size of the mouse pointer, in pixels, per side. +# Default is 16 +# +#mouse_size + +# Speed of mouse tracking. Higher numbers equate to faster +# mouse movement. This option requires that enable_mouse be +# uncommented. +# Legal values are between 1 and 32. Default is 4. +# +#mouse_speed 4 + # Launch specified OSes in graphics mode. By default, rEFInd switches # to text mode and displays basic pre-launch information when launching -# all OSes except OS X. Using graphics mode can produce a more seamless +# all OSes except macOS. Using graphics mode can produce a more seamless # transition, but displays no information, which can make matters # difficult if you must debug a problem. Also, on at least one known # computer, using graphics mode prevents a crash when using the Linux # kernel's EFI stub loader. You can specify an empty list to boot all # OSes in text mode. # Valid options: -# osx - Mac OS X +# osx - macOS # linux - A Linux kernel with EFI stub loader # elilo - The ELILO boot loader # grub - The GRUB (Legacy or 2) boot loader @@ -184,6 +208,7 @@ # csr_rotate - adjusts Apple System Integrity Protection (SIP) # policy. Requires "csr_values" to be set. # about - an "about this program" option +# hidden_tags - manage hidden tags # exit - a tag to exit from rEFInd # shutdown - shuts down the computer (a bug causes this to reboot # many UEFI systems) @@ -193,9 +218,20 @@ # fwupdate - a tag to update the firmware; launches the fwupx64.efi # (or similar) program # netboot - launch the ipxe.efi tool for network (PXE) booting -# Default is shell,memtest,gdisk,apple_recovery,windows_recovery,mok_tool,about,shutdown,reboot,firmware,fwupdate +# Default is shell,memtest,gdisk,apple_recovery,windows_recovery,mok_tool,about,hidden_tags,shutdown,reboot,firmware,fwupdate # -#showtools shell, gdisk, memtest, mok_tool, apple_recovery, windows_recovery, about, reboot, exit, firmware, fwupdate +#showtools shell, gdisk, memtest, mok_tool, apple_recovery, windows_recovery, about, hidden_tags, reboot, exit, firmware, fwupdate + +# Tool binaries to be excluded from the tools line, even if the +# general class is specified in showtools. This enables trimming an +# overabundance of tools, as when you see multiple mok_tool entries +# after installing multiple Linux distributions. +# Just as with dont_scan_files, you can specify a filename alone, a +# full pathname, or a volume identifier (filesystem label, partition +# name, or partition GUID) and a full pathname. +# Default is an empty list (nothing is excluded) +# +#dont_scan_tools ESP2:/EFI/ubuntu/mmx64.efi,gptsync_x64.efi # Boot loaders that can launch a Windows restore or emergency system. # These tend to be OEM-specific. @@ -252,7 +288,7 @@ #scan_delay 5 # When scanning volumes for EFI boot loaders, rEFInd always looks for -# Mac OS X's and Microsoft Windows' boot loaders in their normal locations, +# macOS's and Microsoft Windows' boot loaders in their normal locations, # and scans the root directory and every subdirectory of the /EFI directory # for additional boot loaders, but it doesn't recurse into these directories. # The also_scan_dirs token adds more directories to the scan list. @@ -267,10 +303,13 @@ #also_scan_dirs boot,ESP2:EFI/linux/kernels # Partitions (or whole disks, for legacy-mode boots) to omit from scans. -# For EFI-mode scans, you must specify a volume by its label, which you +# For EFI-mode scans, you normally 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. +# OSes' file browsers. It's also possible to identify a partition by its +# unique GUID (aka its "PARTUUID" in Linux parlance). (Note that this is +# NOT the partition TYPE CODE GUID.) This identifier can be obtained via +# "blkid" in Linux or "diskutil info {partition-id}" in macOS. # For legacy-mode scans, you can specify any subset of the boot loader # description shown when you highlight the option in rEFInd. # The default is "LRS_ESP". @@ -289,9 +328,9 @@ # a hardware manufacturer. If a directory is listed both here and in # also_scan_dirs, dont_scan_dirs takes precedence. Note that this # blacklist applies to ALL the filesystems that rEFInd scans, not just -# the ESP, unless you precede the directory name by a filesystem name, -# as in "myvol:EFI/somedir" to exclude EFI/somedir from the scan on the -# myvol volume but not on other volumes. +# the ESP, unless you precede the directory name by a filesystem name or +# partition unique GUID, as in "myvol:EFI/somedir" to exclude EFI/somedir +# from the scan on the myvol volume but not on other volumes. # #dont_scan_dirs ESP:/EFI/boot,EFI/Dell,EFI/memtest86 @@ -305,11 +344,15 @@ # tools are present in this list, but may appear as second-row # items. # The file may be specified as a bare name (e.g., "notme.efi"), as -# a complete filename (e.g., "/EFI/somedir/notme.efi"), or as a -# complete filename with volume (e.g., "SOMEDISK:/EFI/somedir/notme.efi"). +# a complete pathname (e.g., "/EFI/somedir/notme.efi"), or as a +# complete pathname with volume (e.g., "SOMEDISK:/EFI/somedir/notme.efi" +# or 2C17D5ED-850D-4F76-BA31-47A561740082:/EFI/somedir/notme.efi"). +# OS tags hidden via the Delete or '-' key in the rEFInd menu are +# added to this list, but stored in NVRAM. # The default is shim.efi,shim-fedora.efi,shimx64.efi,PreLoader.efi, # TextMode.efi,ebounce.efi,GraphicsConsole.efi,MokManager.efi,HashTool.efi, -# HashTool-signed.efi,bootmgr.efi +# HashTool-signed.efi,bootmgr.efi,fb{arch}.efi +# (where "{arch}" is the architecture code, like "x64"). # #dont_scan_files shim.efi,MokManager.efi @@ -335,6 +378,25 @@ # #fold_linux_kernels false +# Comma-delimited list of strings to treat as if they were numbers for the +# purpose of kernel version number detection. These strings are matched on a +# first-found basis; that is, if you want to treat both "linux-lts" and +# "linux" as version strings, they MUST be specified as "linux-lts,linux", +# since if you specify it the other way, both vmlinuz-linux and +# vmlinuz-linux-lts will return with "linux" as the "version string," which +# is not what you'd want. Also, if the kernel or initrd file includes both a +# specified string and digits, the "version string" includes both. For +# instance, "vmlinuz-linux-4.8" would yield a version string of "linux-4.8". +# This option is intended for Arch and other distributions that don't include +# version numbers in their kernel filenames, but may provide other uniquely +# identifying strings for multiple kernels. If this feature causes problems +# (say, if your kernel filename includes "linux" but the initrd filename +# doesn't), be sure this is set to an empty string +# (extra_kernel_version_strings "") or comment out the option to disable it. +# Default is no extra version strings +# +#extra_kernel_version_strings linux-lts,linux + # Set the maximum number of tags that can be displayed on the screen at # any time. If more loaders are discovered than this value, rEFInd shows # a subset in a scrolling list. If this value is set too high for the @@ -372,7 +434,7 @@ #default_selection Microsoft #default_selection "+,bzImage,vmlinuz" #default_selection Maintenance 23:30 2:00 -#default_selection "Maintenance,OS X" 1:00 2:30 +#default_selection "Maintenance,macOS" 1:00 2:30 # Enable VMX bit and lock the CPU MSR if unlocked. # On some Intel Apple computers, the firmware does not lock the MSR 0x3A. @@ -385,7 +447,7 @@ # #enable_and_lock_vmx false -# Tell a Mac's EFI that OS X is about to be launched, even when it's not. +# Tell a Mac's EFI that macOS is about to be launched, even when it's not. # This option causes some Macs to initialize their hardware differently than # when a third-party OS is launched normally. In some cases (particularly on # Macs with multiple video cards), using this option can cause hardware to @@ -396,7 +458,7 @@ # some hardware devices. When needed, a value of "10.9" usually works, but # you can experiment with other values. This feature has no effect on # non-Apple computers. -# The default is inactive (no OS X spoofing is done). +# The default is inactive (no macOS spoofing is done). # #spoof_osx_version 10.9 @@ -479,6 +541,28 @@ disabled } +# Below is a more complex Linux example, specifically for Arch Linux. +# This example MUST be modified for your specific installation; if nothing +# else, the PARTUUID code must be changed for your disk. Because Arch Linux +# does not include version numbers in its kernel and initrd filenames, you +# may need to use manual boot stanzas when using fallback initrds or +# multiple kernels with Arch. This example is modified from one in the Arch +# wiki page on rEFInd (https://wiki.archlinux.org/index.php/rEFInd). +menuentry "Arch Linux" { + icon /EFI/refind/icons/os_arch.png + volume "Arch Linux" + loader /boot/vmlinuz-linux + initrd /boot/initramfs-linux.img + options "root=PARTUUID=5028fa50-0079-4c40-b240-abfaf28693ea rw add_efi_memmap" + submenuentry "Boot using fallback initramfs" { + initrd /boot/initramfs-linux-fallback.img + } + submenuentry "Boot to terminal" { + add_options "systemd.unit=multi-user.target" + } + disabled +} + # A sample entry for loading Ubuntu using its standard name for # its GRUB 2 boot loader. Note uses of Linux-style forward slashes menuentry Ubuntu { @@ -520,9 +604,9 @@ # it may serve as a starting point. Note that you'll almost # certainly need to change the "volume" line for this example # to work. -menuentry "My Mac OS X" { +menuentry "My macOS" { icon \EFI\refind\icons\os_mac.png - volume "OS X boot" + volume "macOS boot" loader \System\Library\CoreServices\boot.efi disabled } diff -Nru refind-0.10.4/refind.inf refind-0.11.2/refind.inf --- refind-0.10.4/refind.inf 2015-12-08 17:21:17.000000000 +0000 +++ refind-0.11.2/refind.inf 2017-08-05 23:11:59.000000000 +0000 @@ -1,9 +1,9 @@ ## @file # -# refind.inf file to build rEFInd using the EDK2/UDK2010/UDK2014 development +# refind.inf file to build rEFInd using the EDK2/UDK201# development # kit. # -# Copyright (c) 2012-2015 by Roderick W. Smith +# Copyright (c) 2012-2017 by Roderick W. Smith # Released under the terms of the GPLv3 (or, at your discretion, any later # version), a copy of which should come with this file. # @@ -11,18 +11,18 @@ [Defines] INF_VERSION = 0x00010005 - BASE_NAME = REFIND + BASE_NAME = refind FILE_GUID = B8448DD1-B146-41B7-9D66-98B3A0A404D3 MODULE_TYPE = UEFI_APPLICATION - EDK_RELEASE_VERSION = 0x00020000 - EFI_SPECIFICATION_VERSION = 0x00010000 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010000 VERSION_STRING = 1.0 ENTRY_POINT = efi_main # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# VALID_ARCHITECTURES = IA32 X64 IPF EBC AARCH64 # [Sources] @@ -47,6 +47,7 @@ refind/menu.c refind/mystrings.c refind/screen.c + refind/pointer.c refind/driver_support.c refind/gpt.c refind/crc32.c @@ -63,6 +64,11 @@ MdeModulePkg/MdeModulePkg.dec IntelFrameworkPkg/IntelFrameworkPkg.dec IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec +# Uncomment the below when compiling with OS X +# StdLib/StdLib.dec + +[Packages.XCODE] + StdLib/StdLib.dec [LibraryClasses] UefiApplicationEntryPoint @@ -80,6 +86,11 @@ IoLib PerformanceLib +[LibraryClasses.AARCH64] + BaseStackCheckLib +# Comment out CompilerIntrinsicsLib when compiling for AARCH64 using UDK2014 + CompilerIntrinsicsLib + [Guids] gEfiAcpiTableGuid gEfiAcpi10TableGuid @@ -96,8 +107,6 @@ gEfiPartTypeSystemPartGuid gEfiSmbiosTableGuid gEfiSasDevicePathGuid - - [Ppis] @@ -157,9 +166,13 @@ [BuildOptions.IA32] - XCODE:*_*_*_CC_FLAGS = -Os + XCODE:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO [BuildOptions.X64] - XCODE:*_*_*_CC_FLAGS = -Os + XCODE:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO + +[BuildOptions.AARCH64] + XCODE:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO + GCC:*_*_*_CC_FLAGS = -Os -DEFIAARCH64 -D__MAKEWITH_TIANO diff -Nru refind-0.10.4/refind-install refind-0.11.2/refind-install --- refind-0.10.4/refind-install 2016-10-09 23:10:30.000000000 +0000 +++ refind-0.11.2/refind-install 2017-10-22 20:36:09.000000000 +0000 @@ -8,29 +8,28 @@ # # options include: # "--notesp" to install to the OS X root filesystem rather than to the ESP. -# This option may not be used under Linux. +# This option is valid only under OS X. # "--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. # "--ownhfs {devicefile}" to install to an HFS+ volume that's NOT currently -# an OS X boot volume. +# an OS X boot volume. Valid only in OS X. # "--root {dir}" to specify installation using the specified directory # as the system's root # "--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 -# "--preloader" is synonymous with "--shim" -# "--localkeys" to re-sign x86-64 binaries with a locally-generated key -# "--keepname" to keep refind_x64.efi name as such even when using shim +# driver used on /boot; --nodrivers is OS X default). +# "--shim {shimfile}" to install a shim.efi file for Secure Boot. Valid +# only under Linux. +# "--preloader" is synonymous with "--shim". Valid only under Linux. +# "--encryptkeys" password-protects the Secure Boot private key. +# "--localkeys" to re-sign x86-64 binaries with a locally-generated key. +# Valid only under Linux. +# "--keepname" to keep refind_x64.efi name as such even when using shim. +# Valid only under Linux. # "--yes" to assume a "yes" response to all prompts # -# The "esp" option is valid only on Mac OS X; it causes -# installation to the EFI System Partition (ESP) rather than -# to the current OS X boot partition. Under Linux, this script -# installs to the ESP by default. -# -# This program is copyright (c) 2012-2015 by Roderick W. Smith +# This program is copyright (c) 2012-2017 by Roderick W. Smith # # This program is licensed under the terms of the GNU GPL, version 3, # or (at your option) any later version. @@ -39,6 +38,12 @@ # Revision history: # +# 0.11.1 -- In Linux, be less aggressive about replacing existing NVRAM entries +# 0.11.0 -- Create BOOT.CSV file and option to encrypt SB private key +# 0.10.8 -- Enabled use of shimx64.efi.signed as Shim source file +# 0.10.7 -- Added mm{arch}.efi as equivalent of MokManager.efi +# 0.10.6 -- Improved identification of the root device under macOS. +# 0.10.5 -- More improvement to handling of disks (other than /dev/[sh]d? disks). # 0.10.4 -- Improved handling of disks (other than /dev/[sh]d? disks). # 0.10.2 -- Improved Secure Boot detection in Linux, fixed --usedefault in OS X, # and fixed bug that could cause mountesp to be installed as a FILE @@ -106,6 +111,7 @@ TargetX64="refind_x64.efi" TargetIA32="refind_ia32.efi" LocalKeys=0 +EncryptKeys=0 DeleteRefindDir=0 AlwaysYes=0 @@ -141,6 +147,8 @@ ;; --localkeys) LocalKeys=1 ;; + --encryptkeys) EncryptKeys=1 + ;; --shim | --preloader) ShimSource="$2" ShimType=`basename $ShimSource` shift @@ -155,8 +163,8 @@ ;; * ) echo "Usage: $0 [--notesp | --usedefault {device-file} | --root {dir} |" echo " --ownhfs {device-file} ] [--keepname]" - echo " [--nodrivers | --alldrivers]" - echo " [--localkeys] [--keepname] [--yes]" + echo " [--nodrivers | --alldrivers] [--shim {shimfile}]" + echo " [--localkeys [--encryptkeys]] [--keepname] [--yes]" exit 1 esac shift @@ -197,6 +205,10 @@ exit 0 fi fi + if [[ "$EncryptKeys" == 1 && "$LocalKeys" == 0 ]] ; then + echo "The --encryptkeys option requires the use of --localkeys! Aborting!" + exit 1 + fi RLConfFile="$RootDir/boot/refind_linux.conf" EtcKeysDir="$RootDir/etc/refind.d/keys" } # GetParams() @@ -213,6 +225,33 @@ fi } + +# Get a passphrase for decrpyting a private key, and store it in the +# KeyPassphrase variable. +# $1 Set to "--no-confirm" to skip passphrase input confirmation. +ReadKeyPassphrase() { + if [[ $EncryptKeys == 1 ]] && [ -z "$KeyPassphrase" ]; then + while true; do + echo -n "Private key passphrase (no echo): " + read -r -s + KeyPassphrase="$REPLY" + REPLY="shred value" + echo + if [ "$1" == "--no-confirm" ]; then + break + else + echo -n "Confirm passphrase (no echo): " + read -r -s + echo + if [ "$KeyPassphrase" == "$REPLY" ]; then + REPLY="shred value" + break + fi + fi + done + fi +} + # Determine what CPU type and EFI bit depth we're using. # Sets Platform global variable to lowercase EFI platform code (currently # "x64", "ia32", or "aa64") -- the same code used in filenames. @@ -325,10 +364,16 @@ echo "ShimSource is $ShimSource" if [[ "$ShimSource" != "none" ]] ; then if [[ -f "$ShimSource" ]] ; then - if [[ $ShimType == "shimx64.efi" || $ShimType == "shim.efi" ]] ; then + if [[ $ShimType == "shimx64.efi" || $ShimType == "shim.efi" || $ShimType == "shimx64.efi.signed" ]] ; then TargetX64="grubx64.efi" TargetAARCH64="grubaa64.efi" - MokManagerSource=`dirname "$ShimSource"`/MokManager.efi + MokManagerSource=`dirname "$ShimSource"`/mm$Platform.efi.signed + if [[ ! -f "$MokManagerSource" ]] ; then + MokManagerSource=`dirname "$ShimSource"`/mm$Platform.efi + fi + if [[ ! -f "$MokManagerSource" ]] ; then + MokManagerSource=`dirname "$ShimSource"`/MokManager.efi + fi elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then TargetX64="loader.efi" MokManagerSource=`dirname "$ShimSource"`/HashTool.efi @@ -358,10 +403,13 @@ fi inode1=`ls -i "$MokManagerSource" 2> /dev/null | cut -f 1 -d " "` local TargetMMName=`basename $MokManagerSource` + if [[ $TargetMMName == "mm$Platform.efi.signed" ]] ; then + TargetMMName="mm$Platform.efi" + fi inode2=`ls -i "$InstallDir/$TargetDir/$TargetMMName" 2> /dev/null | cut -f 1 -d " "` if [[ $inode1 != $inode2 ]] ; then if [[ -f "$MokManagerSource" ]] ; then - cp -fb "$MokManagerSource" "$InstallDir/$TargetDir/" + cp -fb "$MokManagerSource" "$InstallDir/$TargetDir/$TargetMMName" fi if [[ $? != 0 ]] ; then Problems=1 @@ -386,7 +434,7 @@ TargetIA32="bootia32.efi" TargetAARCH64="bootaa64.efi" else - if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" || $ShimType = "shimaa64.efi" ]] ; then + if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" || $ShimType == "shimx64.efi.signed" || $ShimType = "shimaa64.efi" ]] ; then TargetX64="grubx64.efi" TargetAARCH64="grubaa64.efi" elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then @@ -721,6 +769,27 @@ fi } # MountDefaultTarget() +# Create a BOOT.CSV file in the same directory as rEFInd, to help in recovery +# should the system's boot entry list be lost +CreateBootCsvFile() { + IConv=`which iconv 2> /dev/null` + if [[ -x "$IConv" ]] ; then + if [[ "$Platform" == "x64" && -d "$InstallDir/$TargetDir" ]] ; then + echo "$TargetX64,rEFInd boot manager,,This is the boot entry for rEFInd" | \ + $IConv -t UCS-2 > "$InstallDir/$TargetDir/BOOT.CSV" + fi + if [[ "$Platform" == "ia32" && -d "$InstallDir/$TargetDir" ]] ; then + echo "$TargetIA32,rEFInd boot manager,,This is the boot entry for rEFInd" | \ + $IConv -t UCS-2 > "$InstallDir/$TargetDir/BOOT.CSV" + fi + if [[ "$Platform" == "aarch64" && -d "$InstallDir/$TargetDir" ]] ; then + echo "$TargetAARCH64,rEFInd boot manager,,This is the boot entry for rEFInd" | \ + $IConv -t UCS-2 > "$InstallDir/$TargetDir/BOOT.CSV" + fi + fi + exit +} # CreateBootCsvFile() + # # A series of OS X support functions.... # @@ -732,11 +801,11 @@ MountOSXESP() { # Identify the ESP. Note: This returns the FIRST ESP found; # if the system has multiple disks, this could be wrong! - Temp=$(mount | sed -n -E "/^(\/dev\/disk[0-9]+s[0-9]+) on \/ \(.*$/s//\1/p") + Temp=$(mount | sed -n -E "/^(\/dev\/disk.*) on \/ \(.*$/s//\1/p") if [ $Temp ]; then Temp=$(diskutil list | grep " EFI " | grep -o 'disk.*' | head -n 1) if [ -z $Temp ]; then - echo "Warning: root device doesn't have an EFI partition" + echo "Warning: root device doesn't have an EFI System Partition" fi else echo "Warning: root device could not be found" @@ -747,7 +816,7 @@ }' ) if [ -z $Temp ]; then - echo "Could not find an EFI partition. Aborting!" + echo "Could not find an EFI System Partition. Aborting!" exit 1 fi fi @@ -795,7 +864,7 @@ <key>ProductName</key> <string>rEFInd</string> <key>ProductVersion</key> - <string>0.10.4</string> + <string>0.11.2</string> </dict> </plist> ENDOFHERE @@ -993,14 +1062,19 @@ echo "Backing up existing $DerKey" cp -f "$DerKey" "$DerKey.backup" 2> /dev/null fi + if [[ $EncryptKeys == 1 ]]; then + KeyEncryptionArgument="" + else + KeyEncryptionArgument="-nodes" + fi "$OpenSSL" req -new -x509 -newkey rsa:2048 -keyout "$PrivateKey" -out "$CertKey" \ - -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/" + $KeyEncryptionArgument -days 3650 -subj "/CN=Locally-generated rEFInd key/" "$OpenSSL" x509 -in "$CertKey" -out "$DerKey" -outform DER chmod 0600 "$PrivateKey" else echo "Using existing local keys...." fi -} +} # GenerateKeys() # Sign a single binary. Requires parameters: # $1 = source file @@ -1008,13 +1082,25 @@ # Also assumes that the SBSign and various key variables are set appropriately. # Aborts script on error SignOneBinary() { - $SBSign --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1" 2>&1 >/dev/null | \ - grep -v "data remaining.*gaps between PE/COFF sections" - if [[ "${PIPESTATUS[0]}" != 0 ]] ; then + ReadKeyPassphrase --no-confirm + if [[ "$EncryptKeys" == 1 ]] ; then + SbSignCommand=$(printf "%q " "$SBSign" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1") + echo "$KeyPassphrase" | + script -qefc "$SbSignCommand" --force /dev/null 2>&1 | ( \ + head -n 2 >/dev/null # Skip the first two lines (incl. passphrase). + grep -v "data remaining.*gaps between PE/COFF sections" + ) + local status="${PIPESTATUS[1]}" + else + "$SBSign" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1" 2>&1 >/dev/null | \ + grep -v "data remaining.*gaps between PE/COFF sections" + local status="${PIPESTATUS[0]}" + fi + if [[ "$status" != 0 ]] ; then echo "Problem signing the binary $1! Aborting!" exit 1 fi -} +} # SignOneBinary() # Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate # key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If @@ -1123,37 +1209,66 @@ echo "ESP was found at $InstallDir using $EspFilesystem" } # FindMountedESP -# Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM. +# Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM, if necessary. # If this fails, sets Problems=1 AddBootEntry() { local PartNum + local InstallDisk + local InstallPart + local InstallPartGuid + local Name + local ExistingEntry + local KeepExistingEntry=0 + local ExistingEntryBootNum + local FirstBoot + Efibootmgr=`which efibootmgr 2> /dev/null` if [[ "$Efibootmgr" ]] ; then - InstallDisk=`grep "$InstallDir" /etc/mtab | cut -d " " -f 1 | cut -c 1-8` - PartNum=`grep "$InstallDir" /etc/mtab | cut -d " " -f 1 | cut -c 9-10` + InstallPart=`grep "$InstallDir" /etc/mtab | cut -d " " -f 1` + for Name in `lsblk -r | grep disk | cut -f 1 -d " "` ; do + if [[ $InstallPart == *"$Name"* ]] ; then + InstallDisk="/dev/"$Name + PartNum=${InstallPart#$InstallDisk} + PartNum=`echo "${PartNum//[!0-9]/}"` + break + fi + done + if [[ -z $InstallDisk || -z $PartNum ]] ; then + echo "Could not identify ESP in AddBootEntry()!" + Problems=1 + return 1 + fi EntryFilename="$TargetDir/$Refind" EfiEntryFilename=`echo ${EntryFilename//\//\\\}` EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g` - ExistingEntry=`"$Efibootmgr" -v | grep -i "$EfiEntryFilename2"` + InstallPartGuid=`blkid -s PARTUUID -o value "$InstallPart"` + FirstBoot=`"$Efibootmgr" | grep BootOrder | cut -c 12-15` + ExistingEntry=`"$Efibootmgr" -v | grep -i "$EfiEntryFilename2" | grep -i "$InstallPartGuid" | head -n 1` + ExistingEntryFirstBoot=`"$Efibootmgr" -v | grep -i "$EfiEntryFilename2" | grep -i "$InstallPartGuid" | grep "Boot$FirstBoot"` if [[ "$ExistingEntry" ]] ; then ExistingEntryBootNum=`echo "$ExistingEntry" | cut -c 5-8` - FirstBoot=`"$Efibootmgr" | grep BootOrder | cut -c 12-15` - if [[ "$ExistingEntryBootNum" != "$FirstBoot" ]] ; then + if [[ ! -n "$ExistingEntryFirstBoot" ]] ; then echo "An existing rEFInd boot entry exists, but isn't set as the default boot" echo "manager. The boot order is being adjusted to make rEFInd the default boot" echo "manager. If this is NOT what you want, you should use efibootmgr to" echo "manually adjust your EFI's boot order." + "$Efibootmgr" -b $ExistingEntryBootNum -B &> /dev/null + else + KeepExistingEntry=1 fi - "$Efibootmgr" -b $ExistingEntryBootNum -B &> /dev/null fi - echo "Installing it!" - if [[ "$KeepName" == 0 ]] ; then - "$Efibootmgr" -c -l "$EfiEntryFilename" -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> /dev/null + if [[ "$KeepExistingEntry" == 0 ]] ; then + echo "Creating new NVRAM entry" + if [[ "$KeepName" == 0 ]] ; then + "$Efibootmgr" -c -l "$EfiEntryFilename" -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> /dev/null + else + "$Efibootmgr" -c -l "$EfiEntryFilename" -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum \ + -u "$TargetShim $TargetX64" &> /dev/null + fi else - "$Efibootmgr" -c -l "$EfiEntryFilename" -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum \ - -u "$TargetShim $TargetX64" &> /dev/null + echo "Keeping existing NVRAM entry" fi if [[ $? != 0 ]] ; then EfibootmgrProblems=1 @@ -1173,7 +1288,7 @@ echo "EFI/BOOT/bootaa64.efi on ARM64 systems) to have it run!" echo else - echo "rEFInd has been set as the default boot manager." + echo "rEFInd is set as the default boot manager." fi } # AddBootEntry() @@ -1281,6 +1396,7 @@ exit 1 fi esac +CreateBootCsvFile if [[ $Problems ]] ; then echo diff -Nru refind-0.10.4/RefindPkg.dec refind-0.11.2/RefindPkg.dec --- refind-0.10.4/RefindPkg.dec 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/RefindPkg.dec 2017-05-26 21:01:23.000000000 +0000 @@ -0,0 +1,8 @@ +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = RefindPkg + PACKAGE_GUID = 0eae8e1b-55be-4c3c-852a-f0273e22ca3c + PACKAGE_VERSION = 4.5.0 + +[Includes] + StdLib/Include diff -Nru refind-0.10.4/RefindPkg.dsc refind-0.11.2/RefindPkg.dsc --- refind-0.10.4/RefindPkg.dsc 1970-01-01 00:00:00.000000000 +0000 +++ refind-0.11.2/RefindPkg.dsc 2017-06-11 18:05:34.000000000 +0000 @@ -0,0 +1,88 @@ +[Defines] + PLATFORM_NAME = Refind + PLATFORM_GUID = d6365e1c-b895-426d-a012-46769b2d02a3 + PLATFORM_VERSION = 4.5.0 + DSC_SPECIFICATION = 0x00010006 + SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM|AARCH64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + # + # Entry point + # + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + # + # UEFI & PI + # + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + # + # Generic Modules + # + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf + UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf + TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PalLib|MdePkg/Library/BasePalLibNull/BasePalLibNull.inf + # + # Misc + # + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf + SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf + S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + BaseStackCheckLib|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf + +[LibraryClasses.AARCH64] + CompilerIntrinsicsLib|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + +[Components] + RefindPkg/refind.inf + RefindPkg/gptsync.inf + RefindPkg/filesystems/ext2.inf + RefindPkg/filesystems/ext4.inf + RefindPkg/filesystems/btrfs.inf + RefindPkg/filesystems/reiserfs.inf + RefindPkg/filesystems/hfs.inf + RefindPkg/filesystems/iso9660.inf + RefindPkg/filesystems/ntfs.inf diff -Nru refind-0.10.4/refind.spec refind-0.11.2/refind.spec --- refind-0.10.4/refind.spec 2016-10-09 23:10:20.000000000 +0000 +++ refind-0.11.2/refind.spec 2017-10-22 20:40:50.000000000 +0000 @@ -1,6 +1,6 @@ Summary: EFI boot manager software Name: refind -Version: 0.10.4 +Version: 0.11.2 Release: 1%{?dist} Summary: EFI boot manager software License: GPLv3 @@ -169,7 +169,11 @@ ./refind-install --shim $ShimFile --yes fi else - ./refind-install --yes + if [[ -n $SBSign && -n $OpenSSL ]] ; then + ./refind-install --localkeys --yes + else + ./refind-install --yes + fi fi # CAUTION: Don't create a %preun or a %postun script that deletes the files @@ -177,6 +181,22 @@ # thus wiping out the just-updated files. %changelog +* Sun Oct 22 2017 R Smith <rodsmith@rodsbooks.com> - 0.11.2 +- Updated spec file for 0.11.2 +* Mon Oct 9 2017 R Smith <rodsmith@rodsbooks.com> - 0.11.1 +- Updated spec file for 0.11.1 +* Sun Aug 13 2017 R Smith <rodsmith@rodsbooks.com> - 0.11.0 +- Updated spec file for 0.11.0 +* Sun Jul 30 2017 R Smith <rodsmith@rodsbooks.com> - 0.10.9 +- Updated spec file for 0.10.9 +* Sun May 21 2017 R Smith <rodsmith@rodsbooks.com> - 0.10.8 +- Updated spec file for 0.10.8 +* Mon Apr 17 2017 R Smith <rodsmith@rodsbooks.com> - 0.10.7 +- Updated spec file for 0.10.7 +* Sun Apr 16 2017 R Smith <rodsmith@rodsbooks.com> - 0.10.6 +- Updated spec file for 0.10.6 +* Sat Mar 4 2017 R Smith <rodsmith@rodsbooks.com> - 0.10.5 +- Updated spec file for 0.10.5 * Sun Oct 9 2016 R Smith <rodsmith@rodsbooks.com> - 0.10.4 - Updated spec file for 0.10.4 * Sun Apr 24 2016 R Smith <rodsmith@rodsbooks.com> - 0.10.3