pax_global_header00006660000000000000000000000064125316223560014517gustar00rootroot0000000000000052 comment=bedb008bbc464818dbeabce6cbd0fec88b5d9381 efibootmgr-0.12/000077500000000000000000000000001253162235600135765ustar00rootroot00000000000000efibootmgr-0.12/.gitignore000066400000000000000000000001251253162235600155640ustar00rootroot00000000000000.*.sw? *.E *.o *.patch *.S efibootmgr-*.tar.* core.* efibootmgr*.zip efibootmgr.spec efibootmgr-0.12/AUTHORS000066400000000000000000000014341253162235600146500ustar00rootroot00000000000000Matt Domsch - All .c and .h files Andreas Schwab - Patches to several .c and .h files Richard Hirst - Patch to efichar.c dann frazier - docbook of manpage - Patches to efibootmgr.c - network boot entry creation in efi.c Joshua Giles - walk the PCI path inserting parent bridge device path components for network boot and EDD30 entries. Alex Williamson - Patch to efi.c and efibootmgr.c for handling BootXXXX values using uppercase hex rather than lowercase, per EFI 1.10 spec. Rogerio Timmers - add option -@ for passing extra variable options in from a file, necessary for setting up some boot entries for Microsoft Windows. efibootmgr-0.12/COPYING000066400000000000000000000431271253162235600146400ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. efibootmgr-0.12/INSTALL000066400000000000000000000004501253162235600146260ustar00rootroot00000000000000Running 'make' builds the file src/efibootmgr/efibootmgr. efibootmgr should be placed into /usr/sbin/. efibootmgr currently requires efivar version 0.19, as well as the pkg-config utility, to be built. efivar: https://github.com/rhinstaller/efivar pkg-config: http://pkgconfig.freedesktop.org efibootmgr-0.12/Makefile000066400000000000000000000057061253162235600152460ustar00rootroot00000000000000 default: all SIGNING_KEY := pjones RELEASE_MAJOR := 0 RELEASE_MINOR := 12 RELEASE_NAME := efibootmgr VERSION := $(RELEASE_MAJOR).$(RELEASE_MINOR) RELEASE_STRING := $(RELEASE_NAME)-$(RELEASE_MAJOR).$(RELEASE_MINOR) CFLAGS = $(EXTRA_CFLAGS) -DEFIBOOTMGR_VERSION=\"$(RELEASE_MAJOR).$(RELEASE_MINOR)\" \ -Wsign-compare -Wall -Werror -g -D_FILE_OFFSET_BITS=64 \ -I/usr/include/efivar MODULES := src BINDIR := /usr/sbin #-------------------------------------------- # Generic Makefile stuff is below. You # should not have to modify any of the stuff # below. #-------------------------------------------- #Included makefiles will add their deps for each stage in these vars: INSTALLDEPS := CLEANDEPS := ALLDEPS := efibootmgr.spec CLEANLIST := efibootmgr.spec #Define the top-level build directory BUILDDIR := $(shell pwd) #Include make rules from each submodule (subdirectory) include $(patsubst %,%/module.mk,$(MODULES)) .PHONY: all clean install_list install install_link post_install tarball echotree default tag archive test-archive all: $(ALLDEPS) clean: clean_list $(CLEANDEPS) clean_list: rm -f $(CLEANLIST) install_list: echotree $(INSTALLDEPS) install: all @make install_list | tools/install.pl copy install_link: all @make install_list | tools/install.pl link post_install: GITTAG = $(RELEASE_STRING) efibootmgr.spec : efibootmgr.spec.in Makefile @sed -e "s,@@VERSION@@,$(VERSION),g" $< > $@ test-archive: efibootmgr.spec @rm -rf /tmp/$(RELEASE_STRING) /tmp/$(RELEASE_STRING)-tmp @mkdir -p /tmp/$(RELEASE_STRING)-tmp @git archive --format=tar $(shell git branch | awk '/^*/ { print $$2 }') | ( cd /tmp/$(RELEASE_STRING)-tmp/ ; tar x ) @git diff | ( cd /tmp/$(RELEASE_STRING)-tmp/ ; patch -s -p1 -b -z .gitdiff ) @mv /tmp/$(RELEASE_STRING)-tmp/ /tmp/$(RELEASE_STRING)/ @cp efibootmgr.spec /tmp/$(RELEASE_STRING)/ @dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/$(RELEASE_STRING).tar.bz2 $(RELEASE_STRING) @rm -rf /tmp/$(RELEASE_STRING) @echo "The archive is in $(RELEASE_STRING).tar.bz2" tag: git tag -s $(GITTAG) refs/heads/master archive: tag efibootmgr.spec @rm -rf /tmp/$(RELEASE_STRING) /tmp/$(RELEASE_STRING)-tmp @mkdir -p /tmp/$(RELEASE_STRING)-tmp @git archive --format=tar $(GITTAG) | ( cd /tmp/$(RELEASE_STRING)-tmp/ ; tar x ) @mv /tmp/$(RELEASE_STRING)-tmp/ /tmp/$(RELEASE_STRING)/ @cp efibootmgr.spec /tmp/$(RELEASE_STRING)/ @dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/$(RELEASE_STRING).tar.bz2 $(RELEASE_STRING) @rm -rf /tmp/$(RELEASE_STRING) @echo "The archive is in $(RELEASE_STRING).tar.bz2" tarball: archive #The rest of the docs... doc_TARGETS += COPYING README INSTALL echotree: @# making directory tree @#RPM FORMAT: @# %defattr(-, user, group) @# %attr(4755,user,group) filename @# filename # Here is a list of variables that are assumed Local to each Makefile. You can # safely stomp on these values without affecting the build. # MODULES # FILES # TARGETS # SOURCES efibootmgr-0.12/README000066400000000000000000000120311253162235600144530ustar00rootroot00000000000000This is efibootmgr, a Linux user-space application to modify the Intel Extensible Firmware Interface (EFI) Boot Manager. This application can create and destroy boot entries, change the boot order, change the next running boot option, and more. Details on the EFI Boot Manager are available from the EFI Specification, v1.02 or above, available from http://www.uefi.org. Note: efibootmgr requires that the kernel module efivars be loaded prior to use. 'modprobe efivars' should do the trick. usage: efibootmgr [options] -a | --active sets bootnum active -A | --inactive sets bootnum inactive -b | --bootnum XXXX modify BootXXXX (hex) -B | --delete-bootnum delete bootnum (hex) -c | --create create new variable bootnum and add to bootorder -d | --disk disk (defaults to /dev/sda) containing loader -e | --edd [1|3|-1] force EDD 1.0 or 3.0 creation variables, or guess -E | --device num EDD 1.0 device number (defaults to 0x80) -g | --gpt force disk w/ invalid PMBR to be treated as GPT -H | --acpi_hid XXXX set the ACPI HID (used with -i) -i | --iface name create a netboot entry for the named interface -l | --loader name (defaults to \elilo.efi) -L | --label label Boot manager display label (defaults to "Linux") -n | --bootnext XXXX set BootNext to XXXX (hex) -N | --delete-bootnext delete BootNext -o | --bootorder XXXX,YYYY,ZZZZ,... explicitly set BootOrder (hex) -O | --delete-bootorder delete BootOrder -p | --part part (defaults to 1) containing loader -q | --quiet be quiet -t | --timeout seconds Boot manager timeout -T | --delete-timeout delete Timeout value -u | --unicode | --UCS-2 pass extra args as UCS-2 (default is ASCII) -U | --acpi_uid XXXX set the ACPI UID (used with -i) -v | --verbose print additional information -V | --version return version and exit -w | --write-signature write unique sig to MBR if needed -@ | --append-binary-args append extra variable args from file (use - to read from stdin). Typical usage: 1) Root can use it to display the current Boot Manager settings. [root@localhost ~]# efibootmgr BootCurrent: 0004 BootNext: 0003 BootOrder: 0004,0000,0001,0002,0003 Timeout: 30 seconds Boot0000* Diskette Drive(device:0) Boot0001* CD-ROM Drive(device:FF) Boot0002* Hard Drive(Device:80)/HD(Part1,Sig00112233) Boot0003* PXE Boot: MAC(00D0B7C15D91) Boot0004* Linux This shows: BootCurrent - the boot entry used to start the currently running system. BootOrder - the boot order as would appear in the boot manager. The boot manager tries to boot the first active entry on this list. If unsuccessful, it tries the next entry, and so on. BootNext - the boot entry which is scheduled to be run on next boot. This superceeds BootOrder for one boot only, and is deleted by the boot manager after first use. This allows you to change the next boot behavior without changing BootOrder. Timeout - the time in seconds between when the boot manager appears on the screen until when it automatically chooses the startup value from BootNext or BootOrder. Five boot entries (0000 - 0004), the active/inactive flag (* means active), and the name displayed on the screen. 2) An OS installer would call 'efibootmgr -c'. This assumes that /boot/efi is your EFI System Partition, and is mounted at /dev/sda1. This creates a new boot option, called "Linux", and puts it at the top of the boot order list. Options may be passed to modify the default behavior. The default OS Loader is elilo.efi. 3) A system administrator wants to change the boot order. She would call 'efibootmgr -o 3,4' to specify PXE boot first, then Linux boot. 4) A system administrator wants to change the boot order for the next boot only. She would call 'efibootmgr -n 4' to specify that the Linux entry be taken on next boot. 5) A system administrator wants to delete the Linux boot option from the menu. 'efibootmgr -b 4 -B' deletes entry 4 and removes it from BootOrder. 6) A system administrator wants to create a boot option to network boot (PXE). Unfortunately, this requires knowing a little more information about your system than can be easily found by efibootmgr, so you've got to pass additional information - the ACPI HID and UID values. These can generally be found by using the EFI Boot Manager (in the EFI environment) to create a network boot entry, then using efibootmgr to print it verbosely. Here's one example: Boot003* Acpi(PNP0A03,0)/PCI(5|0)/Mac(00D0B7F9F510) \ ACPI(a0341d0,0)PCI(0,5)MAC(00d0b7f9f510,0) In this case, the ACPI HID is "0A0341d0" and the UID is "0". For the zx2000 gigE, the HID is "222F" and the UID is "500". For the rx2000 gigE, the HID is "0002" and the UID is "100". You create the boot entry with: 'efibootmgr -c -i eth0 -H 222F -U 500 -L netboot' Many other uses may be found. Please direct any bugs, features, patches, etc. to Peter Jones, https://github.com/vathpela/efibootmgr . efibootmgr-0.12/doc/000077500000000000000000000000001253162235600143435ustar00rootroot00000000000000efibootmgr-0.12/doc/ChangeLog000066400000000000000000000611331253162235600161210ustar00rootroot00000000000000commit de0ca446e7e5439306f7f54806d1a15310588426 Author: Jordan Hargrave Date: Thu Nov 29 10:11:43 2012 -0600 Add patches from fedora release * Wed Nov 28 2012 Matthew Garrett - 0.5.4-14 - efibootmgr-0.5.4-Work-around-broken-Apple-firmware.patch Resolves: #873629 - efibootmgr-0.5.4-Remove-device-path-padding-on-non-Itanium.patch - improve spec conformance commit 9392250bd8668ef7544530d17800dc0271cd8bf3 Author: Jordan Hargrave Date: Tue Apr 24 12:58:57 2012 -0500 From: Lane Winner make_boot_var does not check for failed status with create_variable. This can result in a memory leak. Additionally the user should be notified of the problem. We encounter this issue on one system after filling up the UEFI boot list with dummy devices. The patch fix the problem. It was verified on a Mensa system using RHEL 6.0 Signed-off-by: Yinghai Lu commit 8602b3c41701572669b1f8b9c45409d98405eca2 Author: Peter Jones Date: Wed Jul 14 11:26:49 2010 -0700 Handle sector_size != 512. Disks can have 4kB sectors now, so don't just bail out when that's the case. commit fb3d9a8d9bfd580d23b14b384a393510e0a749ac Author: Matt Domsch Date: Thu Jul 23 14:20:19 2009 -0500 fix disk minor number discovery Raymund Will noted disk_info_from_fd() incorrectly used logical && instead of bitwise & when obtaining the minor number. Reported in https://bugzilla.novell.com/show_bug.cgi?id=524529#c1 commit acac7412e8e0819fc66cdadc06ad4ca535f29b35 Author: Matt Domsch Date: Thu Jul 23 14:18:11 2009 -0500 fix minor memory leak David Binderman noted new_data was being allocated but not freed. Not a big deal as the program exits soon thereafter (and is thus freed), but worth fixing anyhow. Fixes https://bugzilla.novell.com/show_bug.cgi?id=524529#c1 commit c8d6ceaa7b33f952bcf32bc017ce8b5d7d659267 Author: Matt Domsch Date: Fri Jan 11 15:09:12 2008 -0600 update ChangeLog commit 6e6bf6fc7665851798a6c2c92893ebb629e42aff Author: Matt Domsch Date: Fri Jan 11 15:08:12 2008 -0600 replacing elilo < 3.6-6, not -5 per conversation with clumens. commit 4c1fd35da4d0478074e08c10225eb590576acf91 Author: Matt Domsch Date: Thu Jan 3 12:19:28 2008 -0600 RPM spec rewrite for Fedora inclusion efibootmgr is being split out of the elilo SRPM in Fedora, into its own SRPM. commit 833cf4c1266ef72357948299008a22bfb80aa3f3 Author: Matt Domsch Date: Thu Jan 3 12:18:31 2008 -0600 Makefile cleanups bump version take an EXTRA_CFLAGS argument so rpmbuild can give us it's CFLAGS without overriding ours. exclude .git and *~ files from the tarball. commit f0a8b91ba45ff4cf251805cc29aed4f8672c1801 Author: Matt Domsch Date: Thu Jan 3 12:16:35 2008 -0600 src/lib/efi.c: include linux/types.h patch from Fedora. commit f387d5c5bde5d7129e41638e92faa2d38b7ad5a1 Author: Matt Domsch Date: Thu Jan 3 12:15:18 2008 -0600 make sure GPT_HEADER_SIGNATURE is a 64-bit value patch from Debian / Ubuntu 0.5.3-3ubuntu1. commit 7b53efa45112f28e97451bdc16e6c6a68740bd79 Author: Matt Domsch Date: Mon Nov 12 13:31:32 2007 -0600 avoid more unaligned access warnings commit 048197821f9ae2ef9e0c2bd4065649e72332e2dc Author: Matt Domsch Date: Mon Nov 12 12:25:42 2007 -0600 cleanup a few unaligned access warnings commit fa3942b34f1533659af8fe3f6fffb3b4acf4ee10 Author: Matt Domsch Date: Mon Nov 12 12:12:37 2007 -0600 cleanup exit values a little commit c7e236783a79b6977df0ba03db0f92fabffc4b31 Author: Doug Chapman Date: Mon Nov 12 11:32:12 2007 -0500 patch to make efibootmgr have non-zero exit code on errors We have some automated tools that use efibootmgr which are having a hard time detecting when efibootmgr fails since it exits with 0 on many failures. This patch catches (most) errors and exits with non-zero. I also added several error messages for to make it more obvious what was wrong with the command line arguments. Signed-off-by: Matt Domsch commit ecd3c24cb6bee5072ff6d1292456ee3b2cc91019 Author: Matt Domsch Date: Mon Jul 9 16:47:50 2007 +0000 add -lz to libs, needed when libpci happens to need it commit e192a055e0803263b71f89db732de73d5cf4de9b Author: Matt Domsch Date: Mon Jul 9 16:23:34 2007 +0000 apply patch from Dave Jiang to enable cross-building commit 0ee8ecc10109b91d0a77098d5596f56780c862d8 Author: Matt Domsch Date: Thu Aug 11 17:37:04 2005 +0000 v0.5.2.2 commit 8097e44fbc1d022241837f318f57131b1df80adf Author: Matt Domsch Date: Thu Aug 11 17:36:29 2005 +0000 document -@ option commit c87e07e8e479220e696438dbeaf18ce73dafe2c8 Author: Matt Domsch Date: Thu Aug 11 16:55:20 2005 +0000 make efi_variable_t.DataSize be unsigned long, to match kernel implementation. This isn't ideal, I'd prefer to be able to have a 32-bit efibootmgr on a 64-bit kernel, but with efi_status_t being a long also, we're already stuck with needing a native copy. commit 5816bbbf56b37c9eee02a3539e99bffa8aec28e1 Author: Matt Domsch Date: Wed Aug 10 15:59:33 2005 +0000 clean up extra_opts_file handling commit 8b02b12e1153f5bbf5010c16a5614464b5534c88 Author: Matt Domsch Date: Wed Aug 10 15:28:30 2005 +0000 new option -@ grabs extra variable args from a file commit b6185ed1b3c78a37594c2a25200536e7c4172070 Author: Matt Domsch Date: Wed Aug 10 05:34:53 2005 +0000 add -g flag, move _FILE_OFFSET_BITS=64 to Makefile commit d9f0ef65ca0f02003fadb72e3e04d5120bed13a3 Author: Matt Domsch Date: Wed Aug 10 05:30:14 2005 +0000 v0.5.2 commit 3791b2f4bae1795c6f32b1db8cfa03a2cc80fc39 Author: Matt Domsch Date: Wed Aug 10 05:28:23 2005 +0000 move _FILE_OFFSET_BITS definition into Makefile commit 71fc95596c8cb6d2dabcd2672dda053ed23eae7c Author: Matt Domsch Date: Tue Jul 26 19:37:11 2005 +0000 parse PCI domain information in make_net_load_option() on 2.6 kernels commit 2efd000d314e0f339ba71a96cace4132f9f17072 Author: Matt Domsch Date: Tue Jul 26 19:32:24 2005 +0000 properly free allocated memory (caught by valgrind) commit 2108aa866558c48251fc7a89c24693be2d9e3563 Author: Matt Domsch Date: Tue Mar 8 22:54:53 2005 +0000 applied patch from Alex Williamson which causes BootXXXX values to be printed in uppercase hex rather than lowercase. This also now allows the full 64K boot entries, rather than requiring they start with a zero. Release 0.5.1 commit 935544f4a999fbd1d88ab1d3d5d6b3edfcca0861 Author: Matt Domsch Date: Thu Aug 26 21:02:14 2004 +0000 put linux.dell.com in spec file commit 418e9d92ed2cb186c0cc0f1bacd6140934ec8eef Author: Matt Domsch Date: Thu Aug 26 20:27:28 2004 +0000 version 0.5.0-test4 released as v0.5.0 with no code changes commit 833bfe2b8614169a952f554f460e112148bbb3bc Author: Matt Domsch Date: Wed Jun 9 21:51:19 2004 +0000 Add PCI parent devices to device path for netboot and EDD30 entries commit f9381ba1a4c874d04a759b750e3769379067bd9e Author: Matt Domsch Date: Wed Jun 9 21:50:22 2004 +0000 changelog for version 0.5.0-test4 commit a276070603deafa2d2fc8cd7bf8506265583369e Author: Matt Domsch Date: Wed Jun 9 21:49:58 2004 +0000 version 0.5.0-test4 commit 8078fc242cbffa91efa3607b5d03b2948c93f459 Author: Matt Domsch Date: Wed Jun 9 21:49:33 2004 +0000 Don't let read_boot_order() return EFI_NOT_FOUND when it is about to create it. commit 1616ceb1acc0eae3223c8494f4ee829137654ada Author: Matt Domsch Date: Wed Jun 9 21:48:33 2004 +0000 Add libpci to libraries linked in commit 05904ff36fd78cba530cb917dd102af6520fcf56 Author: Matt Domsch Date: Wed Jun 9 21:47:53 2004 +0000 Add Joshua Giles entry commit 51ecfcf601955f4a188de55d07b043a938670bf8 Author: Matt Domsch Date: Sat Apr 24 15:18:57 2004 +0000 fix reversed logic in create_or_edit_variable(), remove extraneous printks in sysfs_read/write() commit 1310d761d7bf0a23b60570afd6774dbc61ad68a8 Author: Matt Domsch Date: Thu Feb 5 23:01:53 2004 +0000 Add ability to add/change/delete Timeout, reflect this everywhere. commit f5cae27869d02ee4c7b89e6dcf6b77fd78932a25 Author: Matt Domsch Date: Fri Dec 19 22:09:01 2003 +0000 Remove extra sizeof() in definition of BLKGETSIZE64. It's unnecessary, and causes new gcc 3.3.x compilers to complain and fail. commit 7c47e6971a98c4edac379224cd5e7cdf51cbe5dc Author: Matt Domsch Date: Tue Sep 9 19:49:27 2003 +0000 More procfs to sysfs cleanups Release version 0.5.0-test1 commit 39fbc273e3632484062506bbbeff2fe7c85c45fc Author: Matt Domsch Date: Thu Sep 4 19:36:18 2003 +0000 - Seperated access to variables through /proc into efivars_procfs.[ch] - Added efivars_sysfs.h to access variables through sysfs. - Moved around some functions, cleaned up some duplication. commit 59ac9c733c6685436ae3fc2f58f21f13b1b422b7 Author: Matt Domsch Date: Mon Aug 11 20:28:05 2003 +0000 * Mon Aug 11 2003 Matt Domsch - fixed unaligned access errors - removed extraneous printing of mac addr when creating netboot entries - sync docbook to README - whitespace cleanups commit 7a37ede2e8bf96bb45ac993d92e9ab5102c61278 Author: Matt Domsch Date: Thu Jul 31 18:50:33 2003 +0000 Adding filelist-rpm commit 9d62f9c5a4972acfa2b9e2385ac4ca30d5820dc7 Author: Matt Domsch Date: Thu Jul 31 18:46:46 2003 +0000 * Thu Jul 31 2003 Matt Domsch - Applied patch from Dann Frazier to enable creating netboot entries. - update AUTHORS with Dann's netboot contribution. - Until we can get the ACPI HID and UID programatically, make the user pass them in when creating a netboot entry. - Add O_DIRECT support for reading the disk. - Fix unparse_hardware_path() for the PCI case - the device and function values were printed in reverse order. - Fix the README file to reflect all the options that can be passed, and add a new item for netboot entries. - whitespace cleanups commit 00098507288b5491976cb9761920e373f172d570 Author: Matt Domsch Date: Fri Oct 25 15:22:44 2002 +0000 - Patch from Fabien Lebaillif - Delamare increases the length of the boot option description from 40 to 64 bytes. commit 359277959b1faca0da15fdff0012b6493e4dbe52 Author: Matt Domsch Date: Fri Oct 25 15:07:41 2002 +0000 Added efibootmgr.8 man page (generated from efibootmgr.8.docbook with docbook2man) commit 458f91ca09a4a073aa7a95d58e70f1adcfe8a54f Author: Matt Domsch Date: Fri Oct 25 15:04:17 2002 +0000 * Tue Oct 22 2002 Matt Domsch - ran docbook2man on the man page Dann Frazier created - Added man page to spec file - Added patches from Dann Frazier - Removes the requirement to be root to run efibootmgr. This lets mortal users run efibootmgr to check the version, and see the --help output. It should also allow efibootmgr to work under security systems without the strict root/non-root dichotomy. - Checks to see if a boot option was specified when a boot option deletion was requested. - Released version 0.4.1 * Sun Jul 21 2002 Matt Domsch - Added kernel_has_blkgetsize64() test, now uses BLKGETSIZE64 if on a known-good kernel. This is important when the Large Block Device (64-bit block address) patch gets merged into the 2.5 kernel. commit f9875103b6fbc426a3c4b52580cafea674f13a7f Author: Matt Domsch Date: Mon Jul 22 01:39:19 2002 +0000 moved uname() call into kernel_has_blkgetsize64, renamed that function commit f479f52feee067ac047c81a3c53e63ae5836a2a6 Author: Matt Domsch Date: Sun Jul 21 04:06:55 2002 +0000 added uname test for calling BLKGETSIZE64 ioctl commit 028b8c693cc0668d1c36cc7f39575bb746025ace Author: Matt Domsch Date: Wed May 1 18:20:25 2002 +0000 moved executable to /usr/sbin/ commit 2a51b704adb0fe61e90c51749c397933321f56f1 Author: Matt Domsch Date: Wed May 1 16:06:27 2002 +0000 moved location of tarball on domsch.com commit cf0ca520e0bf2e4c28aa8b6226d54e34f6529801 Author: Matt Domsch Date: Wed May 1 15:57:22 2002 +0000 tagging as version 0.4.0 commit a02d1ef54c3f831761e1a1a6fb1f52db602475a9 Author: Matt Domsch Date: Wed May 1 15:52:55 2002 +0000 *** empty log message *** commit b001c78107cbab59982b5a7513e6b1832d373b22 Author: Matt Domsch Date: Wed May 1 15:52:01 2002 +0000 use _FILE_OFFSET_BITS commit 7fb06655b7d6ee7358fe14683bd78463933e5d43 Author: Matt Domsch Date: Tue Apr 30 20:14:38 2002 +0000 added 0x's to some printfs commit f7f2433a5a88456555e85f0206410f10db7b943d Author: Matt Domsch Date: Mon Apr 8 18:30:10 2002 +0000 *** empty log message *** commit 983da33189d001578315b633fad1622e06e3f04d Author: Matt Domsch Date: Mon Apr 8 18:27:54 2002 +0000 make sure partition number arg is in the disk commit dd39faedb4ed5e018e4843936b98875747bb57e5 Author: Matt Domsch Date: Sat Apr 6 03:56:36 2002 +0000 *** empty log message *** commit 69811b3cd8286db79af9e4f517cf8e8e7a9c2019 Author: Matt Domsch Date: Sat Apr 6 03:55:13 2002 +0000 added syncs to tarball target - otherwise NFS isn't fast enough to catch the deletions of the CVS directories commit 62933f80aa22e07cb8e93e969fce6a88dc5799b3 Author: Matt Domsch Date: Sat Apr 6 03:42:25 2002 +0000 added __leXX_to_cpu in what currently are commented out lines commit 8f72b1e6d7a09d2908b3c222c42966502bd03084 Author: Matt Domsch Date: Tue Apr 2 23:51:37 2002 +0000 added docbook manpage author commit a6e83d4b26663ed1317217baa539a205efe1b065 Author: Matt Domsch Date: Tue Apr 2 23:49:09 2002 +0000 Makefile: - updated version and date efibootmgr.spec - updated version src/efibootmgr/efibootmgr.c - minor changes src/include/efi.h - efi_guid_t endianness fixups src/include/gpt.h - minor changes src/include/list.h - list_for_each_safe addition src/lib/efi.c - efi_guid_t endianness fixups src/lib/gpt.c - GPT parsing and efi_guid_t endianness fixups commit d227f9f1b4e6468f36ec9a60eb9630cfc1818fef Author: Matt Domsch Date: Tue Apr 2 23:44:52 2002 +0000 *** empty log message *** commit 41e1acbc40f645e06c21037e183c13bee01be969 Author: Matt Domsch Date: Sat Mar 30 23:06:09 2002 +0000 From: bdale@gag.com [mailto:bdale@gag.com] Sent: Saturday, March 30, 2002 2:56 PM To: matt_domsch@exchange.dell.com Subject: man page for efibootmgr Hi. Dann Frazier just sent me sgml source for a man page for efibootmgr, you can find it attached to Debian bug 140514, which you can retrieve from http://bugs.debian.org/140514 Feel free to incorporate this in a future release. I've folded it into my Debian package of efibootmgr for now. Bdale commit 69a8826d5048b03c992e43c89c3086bae30f6bf2 Author: Matt Domsch Date: Fri Jan 18 16:48:54 2002 +0000 Don't use BLKGETSIZE64 ioctl yet, it's broken on kernels 2.4.15-2.4.18, 2.5.0-2.5.3 at least commit 40e24ea0d24fecbc0867494e011aee0b3497c72d Author: Matt Domsch Date: Thu Jan 3 17:54:55 2002 +0000 added back in read last sector IOCTL hack, but only after read() fails commit d29c2b31fc95d45e8232d08d16644dd748a48e6c Author: Matt Domsch Date: Thu Jan 3 17:24:23 2002 +0000 Cleaned up use of scandir namelists commit c380db3c9a897fc66d8fb9c2d7b4ced92df71094 Author: Matt Domsch Date: Thu Jan 3 17:11:04 2002 +0000 really fixed find_write_victim(), added error message when creating a load option on a disk with no partition table. commit cb5fa0f50058ed7078b001b16729b6fb77936c66 Author: Matt Domsch Date: Wed Jan 2 22:41:29 2002 +0000 Fixed find_write_victim(). CV: ---------------------------------------------------------------------- commit 0787a1b3fca6de2923feea974668c01c802f5f86 Author: Matt Domsch Date: Wed Jan 2 20:54:41 2002 +0000 - Changed PROC_DIR_EFI to PROC_DIR_EFI_VARS - write_variable() now searches /proc/efi/vars for a variable that's not the one being written. The EFI 1.1 sample implementation changed the name of the "victim" being written to (was Efi-xxxxx, now EFI-xxxxx), so previous versions of efibootmgr don't work with the new firmware. This should fix that up. commit b4b3ca70f000b6e4fa93a92393014d445920d7ab Author: Matt Domsch Date: Fri Dec 7 23:18:27 2001 +0000 *** empty log message *** commit 7ef8eb0d0d2c9fd7bfa6fb7b0f8b928ac69e9f3b Author: Matt Domsch Date: Fri Dec 7 23:08:02 2001 +0000 printf'ing on IA64, test for disk type (MBR or GPT) fix attempt commit 25a4b1d732ee0fd8fd2e50f4bdb5d809282d0cf9 Author: Matt Domsch Date: Fri Dec 7 20:58:39 2001 +0000 * Fri Dec 7 2001 Matt Domsch - Removed read last sector ioctl hack, it's not needed anymore. The kernel takes care of it for us with a new patch. - Added test for valid PMBR, similar to parted and the kernel. - Added test for returning size of block device as a u64. - Added test for returning sector size as int, and use that. - Changed GPT struct and member names to be more Linux-like. - added -g option to force disk with invalid PMBR to be treated as GPT anyhow. - released v0.4.0 commit 703415a153bbf4b2c2e8770f1bcc61f14c2047c8 Author: Matt Domsch Date: Fri Aug 10 18:40:45 2001 +0000 fixed stat.st_rdev mask commit 04564ca2bff64fc1e7f05617b4335132115acebf Author: Matt Domsch Date: Fri Aug 10 02:49:39 2001 +0000 added uniqueness to MBR signature commit 510449c56f782b5eeabca6431dafe7de748279a3 Author: Matt Domsch Date: Mon Aug 6 15:22:15 2001 +0000 Applied Richard Hirst patch to fix efichar_char_strcmp() commit 272db079c290964077737c5427bf2db97d2e78bb Author: Matt Domsch Date: Fri Aug 3 22:17:48 2001 +0000 warn on duplicate boot entry name; release 0.3.3 commit 58b7e057f6945b28384a86cf3b9e45f50b7fc66a Author: Matt Domsch Date: Mon Jul 30 21:53:26 2001 +0000 really fixed optional data length commit d0ad3bd8d488b2bc965ea78f431e130ac8386b50 Author: Matt Domsch Date: Mon Jul 30 20:57:53 2001 +0000 Added AUTHORS, fixed counting length of optional data commit 5f9f555f8bfc6157183e4c76eae344e43d932394 Author: Matt Domsch Date: Mon Jul 30 15:07:14 2001 +0000 Use device number (i.e. 0800) for signature on MBR disks, as that will be system-unique. commit e089c04b4ce9be4489a44be866334a6034f2e1b3 Author: Matt Domsch Date: Mon Jul 30 13:15:40 2001 +0000 Added check for zero signature on MBR-style disks, and -w flag to write a random signature in that case. commit 23dc432bc1a34a23cffa232565dbc8083225f24e Author: Matt Domsch Date: Fri Jul 27 14:52:54 2001 +0000 tagging with 0.3.3-test3 commit bddbd08efd75daa74575d697c8ebac2714a1ade8 Author: Matt Domsch Date: Fri Jul 27 12:57:23 2001 +0000 added test against running as non-root commit 44ec02672afea5a1c380f906622ff60ef54df956 Author: Matt Domsch Date: Thu Jul 26 15:28:46 2001 +0000 unparse optional args passed to bootloader too. commit c78d3ba9b5337356a1e14affc025a440a37ab3ef Author: Matt Domsch Date: Wed Jul 25 21:13:58 2001 +0000 Bumped version. commit fbb56ba254c297816a278494f5d1e597fa626752 Author: Matt Domsch Date: Wed Jul 25 20:57:46 2001 +0000 Added -t option to allow writing to a file (for testing) commit 287d926464184583cb8b15e639e167b197b2cb4d Author: Matt Domsch Date: Wed Jul 25 19:53:16 2001 +0000 added passing extra args to bootloader commit f8180a6628d18c6cd60ea763715eb15cb8e42940 Author: Matt Domsch Date: Tue May 22 19:04:23 2001 +0000 efi_status_t is now unsigned long, release v0.3.2 commit 303f178a2b7ec830fd7bf6611c1949042b26107c Author: Matt Domsch Date: Tue May 22 14:29:08 2001 +0000 *** empty log message *** commit 56cc281258c4b835407112af6768464f65ad49d4 Author: Matt Domsch Date: Tue May 22 12:49:01 2001 +0000 Applied patch from Andreas Schwab : Here is a patch to fix remove_from_boot_order: --- efibootmgr.c 2001/05/19 00:05:38 1.1 +++ efibootmgr.c 2001/05/22 13:30:31 @@ -319,7 +319,7 @@ uint16_t *new_data, *old_data; int old_i,new_i; - read_boot_order(&boot_order); + status = read_boot_order(&boot_order); if (status != EFI_SUCCESS) return status; /* If it's empty, yea! */ commit 51ab0fa632a9e9a07f3c5d53b3ad53708e690b31 Author: Matt Domsch Date: Fri May 18 22:58:56 2001 +0000 usage() shouldn't make you think you can pass args to the OS loader commit 2d66962dfb107d2d7fe1d931667e29d2a89f4509 Author: Matt Domsch Date: Fri May 18 21:34:45 2001 +0000 Initial commit, should anyone want to make it a separate RPM package. commit 6402c3f02eb8f6b76798fa81da42163ba1f94cea Author: Matt Domsch Date: Fri May 18 21:33:55 2001 +0000 Initial commit commit 064110db2f4ba2a6a5e5cfade5445f8ea6cdecb6 Author: Matt Domsch Date: Fri May 18 21:14:10 2001 +0000 * Fri May 18 2001 Matt Domsch - Padded HARDDRIVE_DEVICE_PATH out to please EFI Boot Manager. - Incorporated patches from Andreas Schwab - replace __u{8,16,32,64} with uint{8,16,32,64}_t - use _FILE_OFFSET_BITS - fix a segfault - release v0.3.0 commit 8bd81a6f41bc91f008c2131c4ff4fcfd3f4baf63 Author: Matt Domsch Date: Tue May 15 22:16:23 2001 +0000 Removed extraneous copyright lines, as this is all written by Matt now. commit 8847549ff1f6ba3d08a2b5a037f8a8c856e850b9 Author: Matt Domsch Date: Tue May 15 21:29:03 2001 +0000 Changed version string to read 0.2.0 commit 80e2fb2dda2365280b85018fca525768e8f454f8 Author: Matt Domsch Date: Tue May 15 21:16:19 2001 +0000 Removed most warnings when compiled with -Wall commit 47a1b011cc497cb6052cc3279865fa567cfcde16 Author: Matt Domsch Date: Tue May 15 20:47:18 2001 +0000 * Ran all files through dos2unix to fix linefeed issues * changed --write to --create in efibootmgr.[ch] * Added #include to efichar.c to remove a warning commit 4576ed6c68cf37913600261c4754a734bc65f3ae Author: mebrown Date: Tue May 15 20:20:54 2001 +0000 add convenience Makefiles commit c138b6297915c2c571932ac029f7b0892926074a Author: mebrown Date: Tue May 15 19:52:36 2001 +0000 readability tweaks to makefiles commit 1bbd86b2e79b2b31166359686a555feee4c4fd7d Author: mebrown Date: Tue May 15 19:43:12 2001 +0000 mostly-working makefile system commit cf4b5b088132c274bd5ef69f7c3b7f9b8af64817 Author: Matt Domsch Date: Tue May 15 18:56:53 2001 +0000 Initial revision efibootmgr-0.12/doc/TODO000066400000000000000000000010251253162235600150310ustar00rootroot00000000000000- support for setting hotkeys - support for driver variables, not just boot variables. - support for arbitrary device paths with -c (including guid parsing) - maintain a list of known GUIDs and print {vendor} instead of the full GUID - accept these for arbitrary paths as well. - these are done in libefivar, but efibootmgr still needs some work on it - MS-DOS style extended partitions - lots more network stuff - IPv6 with various discovery methods - IPv4 w/o dhcp - make sure FCoE works - iscsi - make sure nvme works efibootmgr-0.12/efibootmgr.spec.in000066400000000000000000000054201253162235600172150ustar00rootroot00000000000000Summary: EFI Boot Manager Name: efibootmgr Version: @@VERSION@@ Release: 1%{?dist} Group: System Environment/Base License: GPLv2+ URL: http://github.com/rhinstaller/%{name}/ BuildRequires: git BuildRequires: efivar-libs >= 0.19 , efivar-devel >= 0.19 BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXXXX) # EFI/UEFI don't exist on PPC ExclusiveArch: %{ix86} x86_64 aarch64 # for RHEL / Fedora when efibootmgr was part of the elilo package Conflicts: elilo <= 3.6-6 Obsoletes: elilo <= 3.6-6 Source0: https://github.com/rhinstaller/%{name}/releases/download/%{name}-%{version}/%{name}-%{version}.tar.bz2 %description %{name} displays and allows the user to edit the Intel Extensible Firmware Interface (EFI) Boot Manager variables. Additional information about EFI can be found at http://developer.intel.com/technology/efi/efi.htm and http://uefi.org/. %prep %setup -q git init git config user.email "example@example.com" git config user.name "RHEL Ninjas" git add . git commit -a -q -m "%{version} baseline." git am %{patches} src/man/man8/%{name}.8.gz touch -r src/man/man8/%{name}.8 src/man/man8/%{name}.8.gz install -p --mode 644 src/man/man8/%{name}.8.gz %{buildroot}%{_mandir}/man8 %clean rm -rf %{buildroot} %files %defattr(-,root,root,-) %{_sbindir}/%{name} %{_mandir}/man8/%{name}.8.gz %doc README INSTALL COPYING %changelog * Thu May 28 2015 Peter Jones - 0.12-1 - Update to 0.12 - use libefiboot and libefivar to make device paths and load options - don't depend on -lz or -lpci any more * Tue Oct 21 2014 Peter Jones - 0.11.0-1 - Fix "-n" and friends not being assigned/checked right sometimes from 0.10.0-1 - Generate more archives to avoid people using github's, because they're just bad. * Mon Oct 20 2014 Peter Jones - 0.10.0-1 - Make -o parameter validation work better and be more informative - Better exit values - Fix a segfault with appending ascii arguments. * Tue Sep 09 2014 Peter Jones - 0.8.0-1 - Release 0.8.0 * Mon Jan 13 2014 Peter Jones - 0.6.1-1 - Release 0.6.1 * Mon Jan 13 2014 Jared Dominguez - new home https://github.com/vathpela/efibootmgr * Thu Jan 3 2008 Matt Domsch 0.5.4-1 - split efibootmgr into its own RPM for Fedora/RHEL. * Thu Aug 24 2004 Matt Domsch - new home linux.dell.com * Fri May 18 2001 Matt Domsch - See doc/ChangeLog efibootmgr-0.12/filelist-rpm000066400000000000000000000002051253162235600161250ustar00rootroot00000000000000 %attr(0755,root,root) /usr/sbin %attr(0755,root,root) /usr/sbin/efibootmgr %attr(0444,root,root) /usr/share/man/man8/efibootmgr.8 efibootmgr-0.12/src/000077500000000000000000000000001253162235600143655ustar00rootroot00000000000000efibootmgr-0.12/src/Makefile000066400000000000000000000000241253162235600160210ustar00rootroot00000000000000%: +make -C ../ $* efibootmgr-0.12/src/efibootmgr/000077500000000000000000000000001253162235600165225ustar00rootroot00000000000000efibootmgr-0.12/src/efibootmgr/.gitignore000066400000000000000000000000131253162235600205040ustar00rootroot00000000000000efibootmgr efibootmgr-0.12/src/efibootmgr/Makefile000066400000000000000000000000241253162235600201560ustar00rootroot00000000000000%: +make -C ../ $* efibootmgr-0.12/src/efibootmgr/efibootmgr.c000066400000000000000000001010571253162235600210270ustar00rootroot00000000000000/* efibootmgr.c - Manipulates EFI variables as exported in /proc/efi/vars Copyright (C) 2001-2004 Dell, Inc. 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA This must tie the EFI_DEVICE_PATH to /boot/efi/EFI/redhat/grub.efi The EFI_DEVICE_PATH will look something like: ACPI device path, length 12 bytes Hardware Device Path, PCI, length 6 bytes Messaging Device Path, SCSI, length 8 bytes, or ATAPI, length ?? Media Device Path, Hard Drive, partition XX, length 30 bytes Media Device Path, File Path, length ?? End of Hardware Device Path, length 4 Arguments passed to elilo, as UCS-2 characters, length ?? */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "list.h" #include "efi.h" #include "unparse_path.h" #include "efibootmgr.h" #ifndef EFIBOOTMGR_VERSION #define EFIBOOTMGR_VERSION "unknown (fix Makefile!)" #endif typedef struct _var_entry { char *name; efi_guid_t guid; uint8_t *data; size_t data_size; uint32_t attributes; uint16_t num; list_t list; } var_entry_t; /* global variables */ static LIST_HEAD(boot_entry_list); static LIST_HEAD(blk_list); efibootmgr_opt_t opts; static void free_vars(list_t *head) { list_t *pos, *n; var_entry_t *boot; list_for_each_safe(pos, n, head) { boot = list_entry(pos, var_entry_t, list); if (boot->data) free(boot->data); list_del(&(boot->list)); free(boot); } } static void read_vars(char **namelist, list_t *head) { var_entry_t *entry; int i, rc; if (!namelist) return; for (i=0; namelist[i] != NULL; i++) { if (namelist[i]) { entry = malloc(sizeof(var_entry_t)); if (!entry) goto err; memset(entry, 0, sizeof(var_entry_t)); rc = efi_get_variable(EFI_GLOBAL_GUID, namelist[i], &entry->data, &entry->data_size, &entry->attributes); if (rc < 0) { warn("Skipping unreadable variable \"%s\"", namelist[i]); free(entry); continue; } /* latest apple firmware sets high bit which appears * invalid to the linux kernel if we write it back so * lets zero it out if it is set since it would be * invalid to set it anyway */ entry->attributes = entry->attributes & ~(1 << 31); entry->name = namelist[i]; list_add_tail(&entry->list, head); } } return; err: warn("efibootmgr"); exit(1); } static void free_array(char **array) { int i; if (!array) return; for (i = 0; array[i] != NULL; i++) free(array[i]); free(array); } static int compare(const void *a, const void *b) { int rc = -1; uint16_t n1, n2; memcpy(&n1, a, sizeof(n1)); memcpy(&n2, b, sizeof(n2)); if (n1 < n2) rc = -1; if (n1 == n2) rc = 0; if (n1 > n2) rc = 1; return rc; } /* Return an available boot variable number, or -1 on failure. */ static int find_free_boot_var(list_t *boot_list) { int num_vars=0, i=0, found; uint16_t *vars, free_number; list_t *pos; var_entry_t *boot; list_for_each(pos, boot_list) num_vars++; if (num_vars == 0) return 0; vars = calloc(1, sizeof(uint16_t) * num_vars); if (!vars) return -1; list_for_each(pos, boot_list) { boot = list_entry(pos, var_entry_t, list); vars[i] = boot->num; i++; } qsort(vars, i, sizeof(uint16_t), compare); found = 1; num_vars = i; for (free_number = 0; free_number < num_vars && found; free_number++) { found = 0; list_for_each(pos, boot_list) { boot = list_entry(pos, var_entry_t, list); if (boot->num == free_number) { found = 1; break; } } if (!found) break; } if (found && num_vars) free_number = vars[num_vars-1] + 1; free(vars); return free_number; } static void warn_duplicate_name(list_t *boot_list) { list_t *pos; var_entry_t *boot; efi_load_option *load_option; const unsigned char const *desc; list_for_each(pos, boot_list) { boot = list_entry(pos, var_entry_t, list); load_option = (efi_load_option *) boot->data; desc = efi_loadopt_desc(load_option); if (!strcmp((char *)opts.label, (char *)desc)) { fprintf(stderr, "** Warning ** : %.8s has same label %s\n", boot->name, opts.label); } } } static var_entry_t * make_boot_var(list_t *boot_list) { var_entry_t *boot = NULL; int free_number; list_t *pos; int rc; uint8_t *extra_args = NULL; ssize_t extra_args_size = 0; ssize_t needed=0, sz; if (opts.bootnum == -1) { free_number = find_free_boot_var(boot_list); } else { list_for_each(pos, boot_list) { boot = list_entry(pos, var_entry_t, list); if (boot->num == opts.bootnum) { fprintf(stderr, "** Warning ** : bootnum %04X " "already exists\n", opts.bootnum); return NULL; } } free_number = opts.bootnum; } if (free_number == -1) { warn("efibootmgr: no available boot variables"); return NULL; } /* Create a new var_entry_t object and populate it. */ boot = calloc(1, sizeof(*boot)); if (!boot) { warn("efibootmgr"); return NULL; } sz = get_extra_args(NULL, 0); if (sz < 0) goto err; extra_args_size = sz; boot->data = NULL; boot->data_size = 0; needed = make_linux_load_option(&boot->data, &boot->data_size, NULL, sz); if (needed < 0) goto err; boot->data_size = needed; boot->data = malloc(needed); if (!boot->data) goto err; extra_args = boot->data + needed - extra_args_size; sz = get_extra_args(extra_args, extra_args_size); if (sz < 0) goto err; sz = make_linux_load_option(&boot->data, &boot->data_size, extra_args, extra_args_size); if (sz < 0) goto err; boot->num = free_number; boot->guid = EFI_GLOBAL_GUID; rc = asprintf(&boot->name, "Boot%04X", free_number); if (rc < 0) { warn("efibootmgr"); goto err; } boot->attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; rc = efi_set_variable(boot->guid, boot->name, boot->data, boot->data_size, boot->attributes); if (rc < 0) goto err; list_add_tail(&boot->list, boot_list); return boot; err: if (boot) { if (boot->data) free(boot->data); if (boot->name) { warn("Could not set variable %s", boot->name); free(boot->name); } else { warn("Could not set variable"); } free(boot); } return NULL; } static int read_boot_order(var_entry_t **boot_order) { int rc; var_entry_t *new = NULL, *bo = NULL; if (*boot_order == NULL) { new = calloc(1, sizeof (**boot_order)); if (!new) return -1; *boot_order = bo = new; } else { bo = *boot_order; } rc = efi_get_variable(EFI_GLOBAL_GUID, "BootOrder", &bo->data, &bo->data_size, &bo->attributes); if (rc < 0 && new != NULL) { free(new); *boot_order = NULL; bo = NULL; } if (bo) { /* latest apple firmware sets high bit which appears invalid * to the linux kernel if we write it back so lets zero it out * if it is set since it would be invalid to set it anyway */ bo->attributes = bo->attributes & ~(1 << 31); } return rc; } static int set_boot_u16(const char *name, uint16_t num) { return efi_set_variable(EFI_GLOBAL_GUID, name, (uint8_t *)&num, sizeof (num), EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); } static int add_to_boot_order(uint16_t num) { var_entry_t *boot_order = NULL; uint64_t new_data_size; uint16_t *new_data, *old_data; int rc; rc = read_boot_order(&boot_order); if (rc < 0) { if (errno == ENOENT) rc = set_boot_u16("BootOrder", num); return rc; } /* We've now got an array (in boot_order->data) of the * boot order. First add our entry, then copy the old array. */ old_data = (uint16_t *)boot_order->data; new_data_size = boot_order->data_size + sizeof(uint16_t); new_data = malloc(new_data_size); if (!new_data) return -1; new_data[0] = num; memcpy(new_data+1, old_data, boot_order->data_size); /* Now new_data has what we need */ free(boot_order->data); boot_order->data = (uint8_t *)new_data; boot_order->data_size = new_data_size; rc = efi_set_variable(EFI_GLOBAL_GUID, "BootOrder", boot_order->data, boot_order->data_size, boot_order->attributes); free(boot_order->data); free(boot_order); return rc; } static int remove_dupes_from_boot_order(void) { var_entry_t *boot_order = NULL; uint64_t new_data_size; uint16_t *new_data, *old_data; unsigned int old_i,new_i; int rc; rc = read_boot_order(&boot_order); if (rc < 0) { if (errno == ENOENT) rc = 0; return rc; } old_data = (uint16_t *)(boot_order->data); /* Start with the same size */ new_data_size = boot_order->data_size; new_data = malloc(new_data_size); if (!new_data) return -1; unsigned int old_max = boot_order->data_size / sizeof(*new_data); for (old_i = 0, new_i = 0; old_i < old_max; old_i++) { int copies = 0; unsigned int j; for (j = 0; j < new_i; j++) { if (new_data[j] == old_data[old_i]) { copies++; break; } } if (copies == 0) { /* Copy this value */ new_data[new_i] = old_data[old_i]; new_i++; } } /* Adjust the size if we didn't copy everything. */ new_data_size = sizeof(new_data[0]) * new_i; /* Now new_data has what we need */ free(boot_order->data); boot_order->data = (uint8_t *)new_data; boot_order->data_size = new_data_size; efi_del_variable(EFI_GLOBAL_GUID, "BootOrder"); rc = efi_set_variable(EFI_GLOBAL_GUID, "BootOrder", boot_order->data, boot_order->data_size, boot_order->attributes); free(boot_order->data); free(boot_order); return rc; } static int remove_from_boot_order(uint16_t num) { var_entry_t *boot_order = NULL; uint16_t *data; unsigned int old_i,new_i; int rc; rc = read_boot_order(&boot_order); if (rc < 0) { if (errno == ENOENT) rc = 0; return rc; } /* We've now got an array (in boot_order->data) of the boot order. Squeeze out any instance of the entry we're deleting by shifting the remainder down. */ data = (uint16_t *)(boot_order->data); for (old_i=0,new_i=0; old_i < boot_order->data_size / sizeof(data[0]); old_i++) { if (data[old_i] != num) { if (new_i != old_i) data[new_i] = data[old_i]; new_i++; } } /* If nothing removed, no need to update the BootOrder variable */ if (new_i == old_i) goto all_done; /* BootOrder variable needs to be updated */ efi_del_variable(EFI_GLOBAL_GUID, "BootOrder"); if (new_i == 0) goto all_done; boot_order->data_size = sizeof(data[0]) * new_i; rc = efi_set_variable(EFI_GLOBAL_GUID, "BootOrder", boot_order->data, boot_order->data_size, boot_order->attributes); all_done: free(boot_order->data); free(boot_order); return rc; } static int read_boot_u16(const char *name) { efi_guid_t guid = EFI_GLOBAL_GUID; uint16_t *data = NULL; size_t data_size = 0; uint32_t attributes = 0; int rc; rc = efi_get_variable(guid, name, (uint8_t **)&data, &data_size, &attributes); if (rc < 0) return rc; if (data_size != 2) { if (data != NULL) free(data); errno = EINVAL; return -1; } rc = data[0]; free(data); return rc; } static int delete_boot_var(uint16_t num) { int rc; char name[16]; list_t *pos, *n; var_entry_t *boot; snprintf(name, sizeof(name), "Boot%04X", num); rc = efi_del_variable(EFI_GLOBAL_GUID, name); /* For backwards compatibility, try to delete abcdef entries as well */ if (rc < 0) { if (errno == ENOENT) { snprintf(name, sizeof(name), "Boot%04x", num); rc = efi_del_variable(EFI_GLOBAL_GUID, name); } else if (errno == EPERM) { warn("Could not delete Boot%04X", num); return rc; } } if (rc < 0) { warnx("Boot entry %04X not found", num); return rc; } list_for_each_safe(pos, n, &boot_entry_list) { boot = list_entry(pos, var_entry_t, list); if (boot->num == num) { rc = remove_from_boot_order(num); if (rc < 0) return rc; list_del(&(boot->list)); break; /* short-circuit since it was found */ } } return 0; } static void set_var_nums(list_t *list) { list_t *pos; var_entry_t *var; int num=0, rc; char *name; int warn=0; list_for_each(pos, list) { var = list_entry(pos, var_entry_t, list); rc = sscanf(var->name, "Boot%04X-%*s", &num); if (rc == 1) { var->num = num; name = var->name; /* shorter name */ if ((isalpha(name[4]) && islower(name[4])) || (isalpha(name[5]) && islower(name[5])) || (isalpha(name[6]) && islower(name[6])) || (isalpha(name[7]) && islower(name[7]))) { fprintf(stderr, "** Warning ** : %.8s is not " "EFI 1.10 compliant (lowercase hex in name)\n", name); warn++; } } } if (warn) { fprintf(stderr, "** Warning ** : please recreate these using efibootmgr to remove this warning.\n"); } } static void print_boot_order(uint16_t *order, int length) { int i; printf("BootOrder: "); for (i=0; inum == b) return 1; } return 0; } static void print_error_arrow(char *message, char *buffer, off_t offset) { unsigned int i; fprintf(stderr, "%s: %s\n", message, buffer); for (i = 0; i < strlen(message) + 2; i++) fprintf(stderr, " "); for (i = 0; i < offset; i++) fprintf(stderr, " "); fprintf(stderr, "^\n"); } static int parse_boot_order(char *buffer, uint16_t **order, size_t *length) { uint16_t *data; size_t data_size; size_t len = strlen(buffer); intptr_t end = (intptr_t)buffer + len + 1; int num = 0; char *buf = buffer; while ((intptr_t)buf < end) { size_t comma = strcspn(buf, ","); if (comma == 0) { off_t offset = (intptr_t)buf - (intptr_t)buffer; print_error_arrow("Malformed boot order",buffer,offset); exit(8); } else { num++; } buf += comma + 1; } data = calloc(num, sizeof (*data)); if (!data) return -1; data_size = num * sizeof (*data); int i = 0; buf = buffer; while ((intptr_t)buf < end) { unsigned long result = 0; size_t comma = strcspn(buf, ","); buf[comma] = '\0'; char *endptr = NULL; result = strtoul(buf, &endptr, 16); if ((result == ULONG_MAX && errno == ERANGE) || (endptr && *endptr != '\0')) { print_error_arrow("Invalid boot order", buffer, (intptr_t)endptr - (intptr_t)buffer); free(data); exit(8); } if (result > 0xffff) { fprintf(stderr, "Invalid boot order entry value: %lX\n", result); print_error_arrow("Invalid boot order", buffer, (intptr_t)buf - (intptr_t)buffer); free(data); exit(8); } /* make sure this is an existing boot entry */ if (!is_current_boot_entry(result)) { print_error_arrow("Invalid boot order entry value", buffer, (intptr_t)buf - (intptr_t)buffer); fprintf(stderr,"Boot entry %04lX does not exist\n", result); free(data); exit(8); } data[i++] = result; buf[comma] = ','; buf += comma + 1; } *order = data; *length = data_size; return num; } static int construct_boot_order(char *bootorder, int keep, uint16_t **ret_data, size_t *ret_data_size) { var_entry_t bo; int rc; uint16_t *data = NULL; size_t data_size = 0; rc = parse_boot_order(bootorder, (uint16_t **)&data, &data_size); if (rc < 0 || data_size == 0) { if (data) /* this can't actually happen, but covscan believes */ free(data); return rc; } if (!keep) { *ret_data = data; *ret_data_size = data_size; return 0; } rc = efi_get_variable(EFI_GLOBAL_GUID, "BootOrder", &bo.data, &bo.data_size, &bo.attributes); if (rc < 0) { *ret_data = data; *ret_data_size = data_size; return 0; } /* latest apple firmware sets high bit which appears invalid * to the linux kernel if we write it back so lets zero it out * if it is set since it would be invalid to set it anyway */ bo.attributes = bo.attributes & ~(1 << 31); size_t new_data_size = data_size + bo.data_size; uint16_t *new_data = calloc(1, new_data_size); if (!new_data) { if (data) free(data); return -1; } memcpy(new_data, data, data_size); memcpy(new_data + (data_size / sizeof (*new_data)), bo.data, bo.data_size); free(bo.data); free(data); int new_data_start = data_size / sizeof (uint16_t); int new_data_end = new_data_size / sizeof (uint16_t); int i; for (i = 0; i < new_data_start; i++) { int j; for (j = new_data_start; j < new_data_end; j++) { if (new_data[i] == new_data[j]) { memcpy(new_data + j, new_data + j + 1, sizeof (uint16_t) * (new_data_end-j+1)); new_data_end -= 1; break; } } } *ret_data = new_data; *ret_data_size = new_data_end * sizeof (uint16_t); return 0; } static int set_boot_order(int keep_old_entries) { uint8_t *data = NULL; size_t data_size = 0; int rc; if (!opts.bootorder) return 0; rc = construct_boot_order(opts.bootorder, keep_old_entries, (uint16_t **)&data, &data_size); if (rc < 0 || data_size == 0) return rc; rc = efi_set_variable(EFI_GLOBAL_GUID, "BootOrder", data, data_size, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); free(data); return rc; } static void show_boot_vars() { list_t *pos; var_entry_t *boot; const unsigned char const *description; efi_load_option *load_option; efidp dp = NULL; unsigned char *optional_data = NULL; size_t optional_data_len=0; list_for_each(pos, &boot_entry_list) { boot = list_entry(pos, var_entry_t, list); load_option = (efi_load_option *)boot->data; description = efi_loadopt_desc(load_option); dp = efi_loadopt_path(load_option); if (boot->name) printf("%.8s", boot->name); else printf("Boot%04X", boot->num); printf("%c ", (efi_loadopt_attrs(load_option) & LOAD_OPTION_ACTIVE) ? '*' : ' '); printf("%s", description); if (opts.verbose) { char *text_path = NULL; size_t text_path_len = 0; uint16_t pathlen = efi_loadopt_pathlen(load_option); ssize_t rc; rc = efidp_format_device_path(text_path, text_path_len, dp, pathlen); if (rc < 0) err(18, "Could not parse device path"); rc += 1; text_path_len = rc; text_path = calloc(1, rc); if (!text_path) err(19, "Could not parse device path"); rc = efidp_format_device_path(text_path, text_path_len, dp, pathlen); if (rc < 0) err(20, "Could not parse device path"); printf("\t%s", text_path); free(text_path); text_path_len = 0; /* Print optional data */ rc = efi_loadopt_optional_data(load_option, boot->data_size, &optional_data, &optional_data_len); if (rc < 0) err(21, "Could not parse optional data"); rc = unparse_raw_text(NULL, 0, optional_data, optional_data_len); if (rc < 0) err(22, "Could not parse optional data"); rc += 1; text_path_len = rc; text_path = calloc(1, rc); if (!text_path) err(23, "Could not parse optional data"); rc = unparse_raw_text(text_path, text_path_len, optional_data, optional_data_len); if (rc < 0) err(23, "Could not parse device path"); printf("%s", text_path); free(text_path); } printf("\n"); } } static void show_boot_order() { int rc; var_entry_t *boot_order = NULL; uint16_t *data; rc = read_boot_order(&boot_order); if (rc < 0) { if (errno == ENOENT) printf("No BootOrder is set; firmware will attempt recovery\n"); else perror("show_boot_order()"); return; } /* We've now got an array (in boot_order->data) of the boot order. First add our entry, then copy the old array. */ data = (uint16_t *)boot_order->data; if (boot_order->data_size) { print_boot_order(data, boot_order->data_size / sizeof(uint16_t)); free(boot_order->data); } free(boot_order); } static int set_active_state() { list_t *pos; var_entry_t *boot; efi_load_option *load_option; list_for_each(pos, &boot_entry_list) { boot = list_entry(pos, var_entry_t, list); load_option = (efi_load_option *)boot->data; if (boot->num == opts.bootnum) { if (opts.active == 1) { if (efi_loadopt_attrs(load_option) & LOAD_OPTION_ACTIVE) { return 0; } else { efi_loadopt_attr_set(load_option, LOAD_OPTION_ACTIVE); return efi_set_variable(boot->guid, boot->name, boot->data, boot->data_size, boot->attributes); } } else if (opts.active == 0) { if (!(efi_loadopt_attrs(load_option) & LOAD_OPTION_ACTIVE)) { return 0; } else { efi_loadopt_attr_clear(load_option, LOAD_OPTION_ACTIVE); return efi_set_variable(boot->guid, boot->name, boot->data, boot->data_size, boot->attributes); } } } } /* if we reach here then the bootnumber supplied was not found */ fprintf(stderr,"\nboot entry %x not found\n\n",opts.bootnum); errno = ENOENT; return -1; } static void usage() { printf("efibootmgr version %s\n", EFIBOOTMGR_VERSION); printf("usage: efibootmgr [options]\n"); printf("\t-a | --active sets bootnum active\n"); printf("\t-A | --inactive sets bootnum inactive\n"); printf("\t-b | --bootnum XXXX modify BootXXXX (hex)\n"); printf("\t-B | --delete-bootnum delete bootnum (hex)\n"); printf("\t-c | --create create new variable bootnum and add to bootorder\n"); printf("\t-C | --create-only create new variable bootnum and do not add to bootorder\n"); printf("\t-D | --remove-dups remove duplicate values from BootOrder\n"); printf("\t-d | --disk disk (defaults to /dev/sda) containing loader\n"); printf("\t-e | --edd [1|3|-1] force EDD 1.0 or 3.0 creation variables, or guess\n"); printf("\t-E | --device num EDD 1.0 device number (defaults to 0x80)\n"); printf("\t-g | --gpt force disk with invalid PMBR to be treated as GPT\n"); printf("\t-i | --iface name create a netboot entry for the named interface\n"); #if 0 printf("\t --ip-addr , set local and remote IP addresses\n"); printf("\t --ip-gateway set the network gateway\n"); printf("\t --ip-netmask set the netmask or prefix length\n"); printf("\t --ip-proto TCP|UDP set the IP protocol to be used\n"); printf("\t --ip-port , set local and remote IP ports\n"); printf("\t --ip-origin { {dhcp|static} | { static|stateless|stateful} }\n"); #endif printf("\t-l | --loader name (defaults to \\EFI\\redhat\\grub.efi)\n"); printf("\t-L | --label label Boot manager display label (defaults to \"Linux\")\n"); printf("\t-n | --bootnext XXXX set BootNext to XXXX (hex)\n"); printf("\t-N | --delete-bootnext delete BootNext\n"); printf("\t-o | --bootorder XXXX,YYYY,ZZZZ,... explicitly set BootOrder (hex)\n"); printf("\t-O | --delete-bootorder delete BootOrder\n"); printf("\t-p | --part part (defaults to 1) containing loader\n"); printf("\t-q | --quiet be quiet\n"); printf("\t-t | --timeout seconds set boot manager timeout waiting for user input.\n"); printf("\t-T | --delete-timeout delete Timeout.\n"); printf("\t-u | --unicode | --UCS-2 pass extra args as UCS-2 (default is ASCII)\n"); printf("\t-v | --verbose print additional information\n"); printf("\t-V | --version return version and exit\n"); printf("\t-w | --write-signature write unique sig to MBR if needed\n"); printf("\t-@ | --append-binary-args file append extra args from file (use \"-\" for stdin)\n"); printf("\t-h | --help show help/usage\n"); } static void set_default_opts() { memset(&opts, 0, sizeof(opts)); opts.bootnum = -1; /* auto-detect */ opts.bootnext = -1; /* Don't set it */ opts.active = -1; /* Don't set it */ opts.timeout = -1; /* Don't set it */ opts.edd10_devicenum = 0x80; opts.loader = "\\EFI\\redhat\\grub.efi"; opts.label = (unsigned char *)"Linux"; opts.disk = "/dev/sda"; opts.part = 1; } static void parse_opts(int argc, char **argv) { int c, rc; unsigned int num; int option_index = 0; while (1) { static struct option long_options[] = /* name, has_arg, flag, val */ { {"active", no_argument, 0, 'a'}, {"inactive", no_argument, 0, 'A'}, {"bootnum", required_argument, 0, 'b'}, {"delete-bootnum", no_argument, 0, 'B'}, {"create", no_argument, 0, 'c'}, {"create-only", no_argument, 0, 'C'}, {"remove-dups", no_argument, 0, 'D'}, {"disk", required_argument, 0, 'd'}, {"iface", required_argument, 0, 'i'}, {"edd-device", required_argument, 0, 'E'}, {"edd30", required_argument, 0, 'e'}, {"gpt", no_argument, 0, 'g'}, {"keep", no_argument, 0, 'k'}, {"loader", required_argument, 0, 'l'}, {"label", required_argument, 0, 'L'}, {"bootnext", required_argument, 0, 'n'}, {"delete-bootnext", no_argument, 0, 'N'}, {"bootorder", required_argument, 0, 'o'}, {"delete-bootorder", no_argument, 0, 'O'}, {"part", required_argument, 0, 'p'}, {"quiet", no_argument, 0, 'q'}, {"timeout", required_argument, 0, 't'}, {"delete-timeout", no_argument, 0, 'T'}, {"unicode", no_argument, 0, 'u'}, {"UCS-2", no_argument, 0, 'u'}, {"verbose", optional_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"write-signature", no_argument, 0, 'w'}, {"append-binary-args", required_argument, 0, '@'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "AaBb:cCDd:e:E:gH:i:l:L:n:No:Op:qt:TuU:v::Vw" "@:h", long_options, &option_index); if (c == -1) break; switch (c) { case '@': opts.extra_opts_file = optarg; break; case 'a': opts.active = 1; break; case 'A': opts.active = 0; break; case 'B': opts.delete_boot = 1; break; case 'b': { char *endptr = NULL; unsigned long result; result = strtoul(optarg, &endptr, 16); if ((result == ULONG_MAX && errno == ERANGE) || (endptr && *endptr != '\0')) { print_error_arrow("Invalid bootnum value", optarg, (intptr_t)endptr - (intptr_t)optarg); exit(1); } if (result > 0xffff) { fprintf(stderr, "Invalid bootnum value: %lX\n", result); exit(1); } opts.bootnum = result; break; } case 'c': opts.create = 1; break; case 'C': opts.create = 1; opts.no_boot_order = 1; break; case 'D': opts.deduplicate = 1; break; case 'd': opts.disk = optarg; break; case 'e': rc = sscanf(optarg, "%u", &num); if (rc == 1) opts.edd_version = num; else { fprintf (stderr,"invalid numeric value %s\n", optarg); exit(1); } if (num != 0 && num != 1 && num != 3) { fprintf (stderr, "invalid EDD version %d\n", num); exit(1); } break; case 'E': rc = sscanf(optarg, "%x", &num); if (rc == 1) opts.edd10_devicenum = num; else { fprintf (stderr,"invalid hex value %s\n", optarg); exit(1); } break; case 'g': opts.forcegpt = 1; break; case 'h': usage(); exit(0); break; case 'i': opts.iface = optarg; opts.ip_version = EFIBOOTMGR_IPV4; opts.ip_addr_origin = EFIBOOTMGR_IPV4_ORIGIN_DHCP; break; case 'k': opts.keep_old_entries = 1; break; case 'l': opts.loader = optarg; break; case 'L': opts.label = (unsigned char *)optarg; break; case 'N': opts.delete_bootnext = 1; break; case 'n': { char *endptr = NULL; unsigned long result; result = strtoul(optarg, &endptr, 16); if ((result == ULONG_MAX && errno == ERANGE) || (endptr && *endptr != '\0')) { print_error_arrow("Invalid BootNext value", optarg, (intptr_t)endptr - (intptr_t)optarg); exit(1); } if (result > 0xffff) { fprintf(stderr, "Invalid BootNext value: %lX\n", result); exit(1); } opts.bootnext = result; break; } case 'o': opts.bootorder = optarg; break; case 'O': opts.delete_bootorder = 1; break; case 'p': rc = sscanf(optarg, "%u", &num); if (rc == 1) opts.part = num; else { fprintf (stderr,"invalid numeric value %s\n",optarg); exit(1); } break; case 'q': opts.quiet = 1; break; case 't': rc = sscanf(optarg, "%u", &num); if (rc == 1) { opts.timeout = num; opts.set_timeout = 1; } else { fprintf (stderr,"invalid numeric value %s\n",optarg); exit(1); } break; case 'T': opts.delete_timeout = 1; break; case 'u': opts.unicode = 1; break; case 'v': opts.verbose = 1; if (optarg) { if (!strcmp(optarg, "v")) opts.verbose = 2; if (!strcmp(optarg, "vv")) opts.verbose = 3; rc = sscanf(optarg, "%u", &num); if (rc == 1) opts.verbose = num; else { fprintf (stderr,"invalid numeric value %s\n",optarg); exit(1); } } break; case 'V': opts.showversion = 1; break; case 'w': opts.write_signature = 1; break; default: usage(); exit(1); } } if (optind < argc) { opts.argc = argc; opts.argv = argv; opts.optind = optind; } } int main(int argc, char **argv) { char **boot_names = NULL; var_entry_t *new_boot = NULL; int num; int ret = 0; putenv("LIBEFIBOOT_REPORT_GPT_ERRORS=1"); set_default_opts(); parse_opts(argc, argv); if (opts.showversion) { printf("version %s\n", EFIBOOTMGR_VERSION); return 0; } if (!efi_variables_supported()) errx(2, "EFI variables are not supported on this system."); read_boot_var_names(&boot_names); read_vars(boot_names, &boot_entry_list); set_var_nums(&boot_entry_list); if (opts.delete_boot) { if (opts.bootnum == -1) errx(3, "You must specify a boot entry to delete " "(see the -b option)."); else { ret = delete_boot_var(opts.bootnum); if (ret < 0) err(15, "Could not delete boot variable"); } } if (opts.active >= 0) { if (opts.bootnum == -1) errx(4, "You must specify a boot entry to activate " "(see the -b option"); else { ret = set_active_state(); if (ret < 0) err(16, "Could not set active state"); } } if (opts.create) { warn_duplicate_name(&boot_entry_list); new_boot = make_boot_var(&boot_entry_list); if (!new_boot) err(5, "Could not prepare boot variable"); /* Put this boot var in the right BootOrder */ if (new_boot && !opts.no_boot_order) ret=add_to_boot_order(new_boot->num); if (ret < 0) err(6, "Could not add entry to BootOrder"); } if (opts.delete_bootorder) { ret = efi_del_variable(EFI_GLOBAL_GUID, "BootOrder"); if (ret < 0) err(7, "Could not remove entry from BootOrder"); } if (opts.bootorder) { ret = set_boot_order(opts.keep_old_entries); if (ret < 0) err(8, "Could not set BootOrder"); } if (opts.deduplicate) { ret = remove_dupes_from_boot_order(); if (ret) err(9, "Could not set BootOrder"); } if (opts.delete_bootnext) { if (!is_current_boot_entry(opts.delete_bootnext)) errx(17, "Boot entry %04X does not exist\n", opts.delete_bootnext); ret = efi_del_variable(EFI_GLOBAL_GUID, "BootNext"); if (ret < 0) err(10, "Could not delete BootNext"); } if (opts.delete_timeout) { ret = efi_del_variable(EFI_GLOBAL_GUID, "Timeout"); if (ret < 0) err(11, "Could not delete Timeout"); } if (opts.bootnext >= 0) { if (!is_current_boot_entry(opts.bootnext & 0xFFFF)) errx(12, "Boot entry %X does not exist", opts.bootnext); ret = set_boot_u16("BootNext", opts.bootnext & 0xFFFF); if (ret < 0) err(13, "Could not set BootNext"); } if (opts.set_timeout) { ret = set_boot_u16("Timeout", opts.timeout); if (ret < 0) err(14, "Could not set Timeout"); } if (!opts.quiet && ret == 0) { num = read_boot_u16("BootNext"); if (num >= 0) { printf("BootNext: %04X\n", num); } num = read_boot_u16("BootCurrent"); if (num >= 0) { printf("BootCurrent: %04X\n", num); } num = read_boot_u16("Timeout"); if (num >= 0) { printf("Timeout: %u seconds\n", num); } show_boot_order(); show_boot_vars(); } free_vars(&boot_entry_list); free_array(boot_names); if (ret) return 1; return 0; } efibootmgr-0.12/src/efibootmgr/module.mk000066400000000000000000000014421253162235600203410ustar00rootroot00000000000000efibootmgr_SRCDIR := src/efibootmgr efibootmgr_OBJECTS := efibootmgr.o efibootmgr_TARGETS := efibootmgr efibootmgr_FULLTARGET := \ $(patsubst %, $(efibootmgr_SRCDIR)/%, $(efibootmgr_TARGETS)) efibootmgr_FULLOBJECT := \ $(patsubst %, $(efibootmgr_SRCDIR)/%, $(efibootmgr_OBJECT)) efibootmgr_LIBS := efi.o unparse_path.o efibootmgr_LIBDIR := src/lib efibootmgr_FULLLIB := \ $(patsubst %,$(efibootmgr_LIBDIR)/%,$(efibootmgr_LIBS)) LIBS = $(shell pkg-config --libs efivar efiboot) ALLDEPS += $(efibootmgr_FULLTARGET) CLEANLIST += $(efibootmgr_FULLTARGET) CLEANLIST += $(efibootmgr_FULLOBJECT) bindir_TARGETS += $(efibootmgr_FULLTARGET) $(efibootmgr_FULLTARGET): \ $(efibootmgr_FULLOBJECT) \ $(efibootmgr_FULLLIB) $(CC) $(CFLAGS) $(LDFLAGS) $(efibootmgr_SRCDIR)/efibootmgr.c $^ $(LIBS) -o $@ efibootmgr-0.12/src/include/000077500000000000000000000000001253162235600160105ustar00rootroot00000000000000efibootmgr-0.12/src/include/efi.h000066400000000000000000000034101253162235600167220ustar00rootroot00000000000000/* efi.[ch] - Extensible Firmware Interface definitions Copyright (C) 2001, 2003 Dell Computer Corporation 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef EFI_H #define EFI_H /* * Extensible Firmware Interface * Based on 'Extensible Firmware Interface Specification' * version 1.02, 12 December, 2000 */ #include #include #include /******************************************************* * Boot Option Attributes *******************************************************/ #define LOAD_OPTION_ACTIVE 0x00000001 /******************************************************* * GUIDs *******************************************************/ #define BLKX_UNKNOWN_GUID \ EFI_GUID( 0x47c7b225, 0xc42a, 0x11d2, 0x8e57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) /* Exported functions */ extern int read_boot_var_names(char ***namelist); extern ssize_t make_linux_load_option(uint8_t **data, size_t *data_size, uint8_t *optional_data, size_t optional_data_size); extern ssize_t get_extra_args(uint8_t *data, ssize_t data_size); #endif /* EFI_H */ efibootmgr-0.12/src/include/efibootmgr.h000066400000000000000000000041771253162235600203270ustar00rootroot00000000000000/* efibootmgr.h - Manipulates EFI variables as exported in /proc/efi/vars Copyright (C) 2001 Dell Computer Corporation 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _EFIBOOTMGR_H #define _EFIBOOTMGR_H #define EFIBOOTMGR_IPV4 0 #define EFIBOOTMGR_IPV6 1 #define EFIBOOTMGR_IPV4_ORIGIN_DHCP 0 #define EFIBOOTMGR_IPV4_ORIGIN_STATIC 1 #define EFIBOOTMGR_IPV6_ORIGIN_STATIC 0 #define EFIBOOTMGR_IPV6_ORIGIN_STATELESS 1 #define EFIBOOTMGR_IPV6_ORIGIN_STATEFUL 2 typedef struct { int argc; char **argv; int optind; char *disk; int ip_version; char *iface; char *macaddr; char *local_ip_addr; char *remote_ip_addr; char *gateway_ip_addr; char *ip_netmask; uint16_t ip_local_port; uint16_t ip_remote_port; uint16_t ip_protocol; uint8_t ip_addr_origin; char *loader; unsigned char *label; char *bootorder; int keep_old_entries; char *testfile; char *extra_opts_file; uint32_t part; int edd_version; uint32_t edd10_devicenum; int bootnum; int bootnext; int verbose; int active; int deduplicate; unsigned int delete_boot:1; unsigned int delete_bootorder:1; unsigned int delete_bootnext:1; unsigned int quiet:1; unsigned int showversion:1; unsigned int create:1; unsigned int unicode:1; unsigned int write_signature:1; unsigned int forcegpt:1; unsigned int set_timeout:1; unsigned int delete_timeout:1; unsigned int no_boot_order:1; unsigned short int timeout; } efibootmgr_opt_t; extern efibootmgr_opt_t opts; #endif efibootmgr-0.12/src/include/list.h000066400000000000000000000101061253162235600171320ustar00rootroot00000000000000/* Copied from the Linux 2.4.4 kernel, in linux/include/linux/list.h */ #ifndef _LINUX_LIST_H #define _LINUX_LIST_H /* * Simple doubly linked list implementation. * * Some of the internal functions ("__xxx") are useful when * manipulating whole lists rather than single entries, as * sometimes we already know the next/prev entries and we can * generate better code by using them directly rather than * using the generic single-entry routines. */ struct list_head { struct list_head *next, *prev; }; typedef struct list_head list_t; #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) /* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static __inline__ void __list_add(struct list_head * new, struct list_head * prev, struct list_head * next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } /** * list_add - add a new entry * @new: new entry to be added * @head: list head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */ static __inline__ void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } /** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } /* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static __inline__ void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; } /** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty on entry does not return true after this, the entry is in an undefined state. */ static __inline__ void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); } /** * list_del_init - deletes entry from list and reinitialize it. * @entry: the element to delete from the list. */ static __inline__ void list_del_init(struct list_head *entry) { __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); } /** * list_empty - tests whether a list is empty * @head: the list to test. */ static __inline__ int list_empty(struct list_head *head) { return head->next == head; } /** * list_splice - join two lists * @list: the new list to add. * @head: the place to add it in the first list. */ static __inline__ void list_splice(struct list_head *list, struct list_head *head) { struct list_head *first = list->next; if (first != list) { struct list_head *last = list->prev; struct list_head *at = head->next; first->prev = head; head->next = first; last->next = at; at->prev = last; } } /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop counter. * @head: the head for your list. */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) /** * list_for_each_safe - iterate over a list safe against removal of list entry * @pos: the &struct list_head to use as a loop counter. * @n: another &struct list_head to use as temporary storage * @head: the head for your list. */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) #endif efibootmgr-0.12/src/include/module.mk000066400000000000000000000000301253162235600176170ustar00rootroot00000000000000CFLAGS += -Isrc/include efibootmgr-0.12/src/include/unparse_path.h000066400000000000000000000017611253162235600206570ustar00rootroot00000000000000/* unparse_path.[ch] Copyright (C) 2001 Dell Computer Corporation 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _UNPARSE_PATH_H #define _UNPARSE_PATH_H #include #include "efi.h" ssize_t unparse_raw_text(char *buffer, size_t buffer_size, uint8_t *p, uint64_t length); #endif efibootmgr-0.12/src/lib/000077500000000000000000000000001253162235600151335ustar00rootroot00000000000000efibootmgr-0.12/src/lib/Makefile000066400000000000000000000000241253162235600165670ustar00rootroot00000000000000%: +make -C ../ $* efibootmgr-0.12/src/lib/efi.c000066400000000000000000000240021253162235600160400ustar00rootroot00000000000000/* efivars_proc.[ch] - Manipulates EFI variables as exported in /proc/efi/vars Copyright (C) 2001,2003 Dell Computer Corporation 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "efi.h" #include "efibootmgr.h" #include "list.h" static int select_boot_var_names(const efi_guid_t *guid, const char *name) { efi_guid_t global = EFI_GLOBAL_GUID; if (!strncmp(name, "Boot", 4) && isxdigit(name[4]) && isxdigit(name[5]) && isxdigit(name[6]) && isxdigit(name[7]) && !memcmp(guid, &global, sizeof (global))) return 1; return 0; } typedef __typeof__(select_boot_var_names) filter_t; static int cmpstringp(const void *p1, const void *p2) { const char *s1 = *(const char **)p1; const char *s2 = *(const char **)p2; return strcoll(s1, s2); } static int read_var_names(filter_t filter, char ***namelist) { int rc; efi_guid_t *guid = NULL; char *name = NULL; char **newlist = NULL; int nentries = 0; int i; rc = efi_variables_supported(); if (!rc) return -1; while ((rc = efi_get_next_variable_name(&guid, &name)) > 0) { if (!filter(guid, name)) continue; char *aname = strdup(name); if (!aname) { rc = -1; break; } char **tmp = realloc(newlist, (++nentries + 1) * sizeof (*newlist)); if (!tmp) { free(aname); rc = -1; break; } tmp[nentries] = NULL; tmp[nentries-1] = aname; newlist = tmp; } if (rc == 0 && newlist) { qsort(newlist, nentries, sizeof (char *), cmpstringp); *namelist = newlist; } else { if (newlist) { for (i = 0; newlist[i] != NULL; i++) free(newlist[i]); free(newlist); } } return rc; } int read_boot_var_names(char ***namelist) { return read_var_names(select_boot_var_names, namelist); } #if 0 static int get_virt_pci(char *name, unsigned char *bus, unsigned char *device, unsigned char *function) { char inbuf[64], outbuf[128]; ssize_t lnksz; if (snprintf(inbuf, sizeof inbuf, "/sys/bus/virtio/devices/%s", name) >= (ssize_t)(sizeof inbuf)) { return -1; } lnksz = readlink(inbuf, outbuf, sizeof outbuf); if (lnksz == -1 || lnksz == sizeof outbuf) { return -1; } outbuf[lnksz] = '\0'; if (sscanf(outbuf, "../../../devices/pci0000:00/0000:%hhx:%hhx.%hhx", bus, device, function) != 3) { return -1; } return 0; } /** * make_net_load_option() * @iface - interface name (input) * @buf - buffer to write structure to * @size - size of buf * * Returns -1 on error, size written on success, or size needed if size == 0. */ static ssize_t make_net_load_option(char *iface, uint8_t *buf, size_t size) { /* copied pretty much verbatim from the ethtool source */ int fd = 0, err; unsigned char bus, slot, func; struct ifreq ifr; struct ethtool_drvinfo drvinfo; ssize_t needed; off_t buf_offset; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, iface); drvinfo.cmd = ETHTOOL_GDRVINFO; ifr.ifr_data = (caddr_t)&drvinfo; /* Open control socket */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("Cannot get control socket"); return -1; } err = ioctl(fd, SIOCETHTOOL, &ifr); if (err < 0) { perror("Cannot get driver information"); close(fd); return -1; } if (strncmp(drvinfo.bus_info, "virtio", 6) == 0) { err = get_virt_pci(drvinfo.bus_info, &bus, &slot, &func); if (err < 0) { close(fd); return err; } } else { /* The domain part was added in 2.6 kernels. * Test for that first. */ err = sscanf(drvinfo.bus_info, "%*x:%hhx:%hhx.%hhx", &bus, &slot, &func); if (err != 3) { err = sscanf(drvinfo.bus_info, "%hhx:%hhx.%hhx", &bus, &slot, &func); if (err != 3) { perror("Couldn't parse device location string."); close(fd); return -1; } } } err = ioctl(fd, SIOCGIFHWADDR, &ifr); if (err < 0) { close(fd); perror("Cannot get hardware address."); return -1; } buf_offset = 0; needed = efidp_make_acpi_hid(buf, size?size-buf_offset:0, opts.acpi_hid, opts.acpi_uid); if (needed < 0) { err_needed: close(fd); return needed; } buf_offset += needed; needed = make_pci_device_path(bus, (uint8_t)slot, (uint8_t)func, buf + buf_offset, size == 0 ? 0 : size - buf_offset); if (needed < 0) goto err_needed; buf_offset += needed; needed = efidp_make_mac_addr(buf, size?size-buf_offset:0, ifr.ifr_ifru.ifru_hwaddr.sa_family, (uint8_t*)ifr.ifr_ifru.ifru_hwaddr.sa_data, sizeof (ifr.ifr_ifru.ifru_hwaddr.sa_data)); if (needed < 0) goto err_needed; buf_offset += needed; if (opts.ipv4) { needed = make_ipv4_addr_device_path(fd, ); if (needed < 0) goto err_needed; buf_offset += needed; } if (opts.ipv6) { needed = make_ipv6_addr_device_path(fd, ); if (needed < 0) goto err_needed; buf_offset += needed; } close(fd); needed = efidp_make_end_entire(buf,size?size-buf_offset:0); if (needed < 0) return needed; buf_offset += needed; return buf_offset; } #endif static int get_edd_version(void) { efi_guid_t guid = BLKX_UNKNOWN_GUID; uint8_t *data = NULL; size_t data_size = 0; uint32_t attributes; efidp_header *path; int rc = 0; /* Allow global user option override */ switch (opts.edd_version) { case 0: /* No EDD information */ return 0; case 1: /* EDD 1.0 */ return 1; case 3: /* EDD 3.0 */ return 3; default: break; } rc = efi_get_variable(guid, "blk0", &data, &data_size, &attributes); if (rc < 0) return rc; path = (efidp_header *)data; if (path->type == 2 && path->subtype == 1) return 3; return 1; } /** * make_linux_load_option() * @data - load option returned * *data_size - load option size returned * * Returns 0 on error, length of load option created on success. */ ssize_t make_linux_load_option(uint8_t **data, size_t *data_size, uint8_t *optional_data, size_t optional_data_size) { ssize_t needed; uint32_t attributes = opts.active ? LOAD_OPTION_ACTIVE : 0; int saved_errno; efidp dp = NULL; if (opts.iface && opts.ip_version == EFIBOOTMGR_IPV4) { needed = efi_generate_ipv4_device_path(NULL, 0, opts.iface, opts.local_ip_addr, opts.remote_ip_addr, opts.gateway_ip_addr, opts.ip_netmask, opts.ip_local_port, opts.ip_remote_port, opts.ip_protocol, opts.ip_addr_origin); if (needed < 0) return -1; if (data_size && *data_size) { dp = malloc(needed); needed = efi_generate_ipv4_device_path( (uint8_t *)dp, needed, opts.iface, opts.local_ip_addr, opts.remote_ip_addr, opts.gateway_ip_addr, opts.ip_netmask, opts.ip_local_port, opts.ip_remote_port, opts.ip_protocol, opts.ip_addr_origin); if (needed < 0) { free(dp); return -1; } } } else if (opts.iface && opts.ip_version == EFIBOOTMGR_IPV6) { errno = ENOSYS; return -1; } else { uint32_t options = EFIBOOT_ABBREV_HD; int edd; /* there's really no telling if this is even the right disk, * but... I also never see blk0 exported to runtime on any * hardware, so it probably only happens on some old itanium * box from the beginning of time anyway. */ edd = get_edd_version(); switch (edd) { case 1: options = EFIBOOT_ABBREV_EDD10; break; case 3: options = EFIBOOT_ABBREV_NONE; break; } needed = efi_generate_file_device_path_from_esp(NULL, 0, opts.disk, opts.part, opts.loader, options, opts.edd10_devicenum); if (needed < 0) return -1; if (data_size && *data_size) { dp = malloc(needed); if (dp == NULL) return -1; needed = efi_generate_file_device_path_from_esp( (uint8_t *)dp, needed, opts.disk, opts.part, opts.loader, options, opts.edd10_devicenum); if (needed < 0) { free(dp); return -1; } } } needed = efi_loadopt_create(*data, *data_size, attributes, dp, needed, opts.label, optional_data, optional_data_size); if (dp) { saved_errno = errno; free(dp); dp = NULL; errno = saved_errno; } if (needed < 0) return -1; return needed; } ssize_t get_extra_args(uint8_t *data, ssize_t data_size) { int i; ssize_t needed = 0, sz; off_t off = 0; if (opts.extra_opts_file) { needed = efi_loadopt_args_from_file(data, data_size, opts.extra_opts_file); if (needed < 0) { fprintf(stderr, "efibootmgr: get_extra_args: %m\n"); return -1; } } for (i = opts.optind; i < opts.argc; i++) { int space = (i < opts.argc - 1) ? 1 : 0; if (opts.unicode) { sz = efi_loadopt_args_as_ucs2( (uint16_t *)(data+off), data_size?data_size+off:0, opts.argv[i]); if (sz < 0) return -1; off += sz; if (data && off < data_size-2 && space) { data[off] = '\0'; data[off+1] = '\0'; } off += space * sizeof (uint16_t); } else { sz = efi_loadopt_args_as_utf8(data+off, data_size?data_size+off:0, opts.argv[i]); if (sz < 0) return -1; off += sz; if (data && off < data_size-1 && space) { data[off] = '\0'; } off += space; } needed += off; } return needed; } efibootmgr-0.12/src/lib/module.mk000066400000000000000000000000561253162235600167520ustar00rootroot00000000000000CFLAGS += -Isrc/lib CLEANLIST += src/lib/*.o efibootmgr-0.12/src/lib/unparse_path.c000066400000000000000000000031141253162235600177670ustar00rootroot00000000000000/* unparse_path.[ch] Copyright (C) 2001 Dell Computer Corporation 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* For PRIx64 */ #define __STDC_FORMAT_MACROS #include #include #include #include #include #include #include #include #include "efi.h" #include "unparse_path.h" /* Avoid unaligned access warnings */ #define get(buf, obj) *(typeof(obj) *)memcpy(buf, &obj, sizeof(obj)) ssize_t unparse_raw_text(char *buffer, size_t buffer_size, uint8_t *p, uint64_t length) { uint64_t i; unsigned char c; ssize_t needed; size_t buf_offset = 0; for (i=0; i < length; i++) { c = p[i]; if (c < 32 || c > 127) c = '.'; needed = snprintf(buffer + buf_offset, buffer_size == 0 ? 0 : buffer_size - buf_offset, "%c", c); if (needed < 0) return -1; buf_offset += needed; } return buf_offset; } efibootmgr-0.12/src/man/000077500000000000000000000000001253162235600151405ustar00rootroot00000000000000efibootmgr-0.12/src/man/man8/000077500000000000000000000000001253162235600160035ustar00rootroot00000000000000efibootmgr-0.12/src/man/man8/efibootmgr.8000066400000000000000000000147151253162235600202410ustar00rootroot00000000000000.\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "EFIBOOTMGR" "8" "11 January 2012" "" "" .SH NAME efibootmgr \- manipulate the EFI Boot Manager .SH SYNOPSIS \fBefibootmgr\fR [ \fB-a\fR ] [ \fB-A\fR ] [ \fB-b \fIXXXX\fB\fR ] [ \fB-B \fIXXXX\fB\fR ] [ \fB-c\fR ] [ \fB-d \fIDISK\fB\fR ] [ \fB-D\fR ] [ \fB-e \fI1|3|-1\fB\fR ] [ \fB-E \fINUM\fB\fR ] [ \fB-g\fR ] [ \fB-H \fIXXXX\fB\fR ] [ \fB-i \fINAME\fB\fR ] [ \fB-l \fINAME\fB\fR ] [ \fB-L \fILABEL\fB\fR ] [ \fB-n \fIXXXX\fB\fR ] [ \fB-N\fR ] [ \fB-o \fIXXXX\fB,\fIYYYY\fB,\fIZZZZ\fB\fR\fI ...\fR ] [ \fB-O\fR ] [ \fB-p \fIPART\fB\fR ] [ \fB-q\fR ] [ \fB-t \fIseconds\fB\fR ] [ \fB-T\fR ] [ \fB-u\fR ] [ \fB-U \fIXXXX\fB\fR ] [ \fB-v\fR ] [ \fB-V\fR ] [ \fB-w\fR ] [ \fB-@ \fIfile\fB\fR ] .SH "DESCRIPTION" .PP \fBefibootmgr\fR is a userspace application used to modify the Intel Extensible Firmware Interface (EFI) Boot Manager. This application can create and destroy boot entries, change the boot order, change the next running boot option, and more. .PP Details on the EFI Boot Manager are available from the EFI Specification, v1.02 or later, available from: .sp .RS .B "Note:" efibootmgr requires that the kernel support access to EFI non-volatile variables through \fI/sys/firmware/efi/vars\fR or \fI/sys/firmware/efi/efivars/\fR. .RE .SH "OPTIONS" .PP The following is a list of options accepted by efibootmgr: .TP \fB-a | --active\fR Sets bootnum active .TP \fB-A | --inactive\fR Sets bootnum inactive .TP \fB-b | --bootnum \fIXXXX\fB\fR Modify Boot\fIXXXX\fR (hex) .TP \fB-B | --delete-bootnum\fR Delete bootnum (hex) .TP \fB-c | --create\fR Create new variable bootnum and add to bootorder .TP \fB-d | --disk \fIDISK\fB\fR The disk containing the loader (defaults to \fI/dev/sda\fR) .TP \fB-D | --remove-dups\fR Remove duplicated entries from BootOrder .TP \fB-e | --edd30 \fI1|3|-1\fB\fR Force EDD 1.0 or 3.0 creation variables, or guess. .TP \fB-E | --edd-device \fINUM\fB\fR EDD 1.0 device number (defaults to 0x80) .TP \fB-g | --gpt\fR Force disk with invalid PMBR to be treated as GPT .TP \fB-i | --iface \fINAME\fB\fR create a netboot entry for the named interface .TP \fB-l | --loader \fINAME\fB\fR Specify a loader (defaults to \fI\\\\elilo.efi\fR) .TP \fB-L | --label \fILABEL\fB\fR Boot manager display label (defaults to "Linux") .TP \fB-n | --bootnext \fIXXXX\fB\fR Set BootNext to XXXX (hex) .TP \fB-N | --delete-bootnext\fR Delete BootNext .TP \fB-o | --bootorder \fIXXXX\fB,\fIYYYY\fB,\fIZZZZ\fB\fR Explicitly set BootOrder (hex). Any value from 0 to FFFF is accepted so long as it corresponds to an existing Boot#### variable, and zero padding is not required. .TP \fB-O | --delete-bootorder\fR Delete BootOrder .TP \fB-p | --part \fIPART\fB\fR Partition number containing the bootloader (defaults to 1) .TP \fB-q | --quiet\fR Quiet mode - supresses output. .TP \fB-t | --timeout \fIseconds\fB\fR Boot Manager timeout, in \fIseconds\fR\&. .TP \fB-T | --delete-timeout\fR Delete Timeout variable. .TP \fB-u | --unicode | --UCS-2 \fR pass extra command line arguments as UCS-2 (default is ASCII) .TP \fB-v | --verbose\fR Verbose mode - prints additional information .TP \fB-V | --version\fR Just print version string and exit. .TP \fB-w | --write-signature\fR write unique signature to the MBR if needed .TP \fB-@ | --append-binary-args \fR append extra variable args from file (use - to read from stdin). Data in file is appended as command line arguments to the boot loader command, with no modification to the data, so you can pass any binary or text data necessary. .SH "EXAMPLES" .TP 3 1. .SS "DISPLAYING THE CURRENT SETTINGS (MUST BE ROOT)." .PP .PP .nf .B [root@localhost ~]# efibootmgr BootCurrent: 0004 BootNext: 0003 BootOrder: 0004,0000,0001,0002,0003 Timeout: 30 seconds Boot0000* Diskette Drive(device:0) Boot0001* CD-ROM Drive(device:FF) Boot0002* Hard Drive(Device:80)/HD(Part1,Sig00112233) Boot0003* PXE Boot: MAC(00D0B7C15D91) Boot0004* Linux .fi .PP This shows: .RS .TP 0.2i \(bu BootCurrent - the boot entry used to start the currently running system .TP 0.2i \(bu BootOrder - the boot order as would appear in the boot manager. The boot manager tries to boot the first active entry in this list. If unsuccessful, it tries the next entry, and so on. .TP 0.2i \(bu BootNext - the boot entry which is scheduled to be run on next boot. This supercedes BootOrder for one boot only, and is deleted by the boot manager after first use. This allows you to change the next boot behavior without changing BootOrder. .TP 0.2i \(bu Timeout - the time in seconds between when the boot manager appears on the screen until when it automatically chooses the startup value from BootNext or BootOrder. .TP 0.2i \(bu Five boot entries (0000 - 0004), along with the active/inactive flag (* means active) and the name displayed on the screen. .RE .TP 3 2. .SS "CREATING A NEW BOOT OPTION" .PP An OS installer would call \fBefibootmgr -c\fR\&. This assumes that \fI/boot/efi\fR is your EFI System Partition, and is mounted at \fI/dev/sda1\fR\&. This creates a new boot option, called "Linux", and puts it at the top of the boot order list. Options may be passed to modify the default behavior. The default OS Loader is \fIelilo.efi\fR\&. .TP 3 3. .SS "CHANGING THE BOOT ORDER" .PP Assuming the configuration in Example #1, \fBefibootmgr -o 3,4\fR could be called to specify PXE boot first, then Linux boot. .TP 3 4. .SS "CHANGING THE BOOT ORDER FOR THE NEXT BOOT ONLY" .PP Assuming the configuration in Example #1, \fBefibootmgr -n 4\fR could be called to specify that the Linux entry be taken on next boot. .TP 3 5. .SS "DELETING A BOOT OPTION" .PP Assuming the configuration in Example #1, \fBefibootmgr -b 4 -B\fR could be called to delete entry 4 and remove it from the BootOrder. .TP 3 6. .SS "CREATING NETWORK BOOT ENTRIES" .PP A system administrator wants to create a boot option to network boot. You create the boot entry with: \fBefibootmgr -c -i eth0 -L netboot [ -l '\\filename.efi' ]\fR .SH "BUGS" .PP Please direct any bugs, features, patches, etc. to Peter Jones: https://github.com/rhinstaller/efibootmgr \&. .SH "AUTHOR" .PP This man page was generated by dann frazier for the Debian GNU/Linux operating system, but may be used by others. .SH "SEE ALSO" .PP elilo(1) efibootmgr-0.12/src/module.mk000066400000000000000000000012371253162235600162060ustar00rootroot00000000000000#add our stuff first... our children need to wait for us to finish INSTALLDEPS += bindir_LIST MODULES := src/efibootmgr src/lib src/include include $(patsubst %,%/module.mk,$(MODULES)) # Common stuff to copy into the common directories # Note that the stuff below bindir_LIST is all on one line... bindir_LIST: @if [ ! -z "$(bindir_TARGETS)" ]; then \ echo "R-M-: %attr(0755,root,root) $(BINDIR)" ;\ for file in $(bindir_TARGETS) ;\ do \ echo "-C--: $(BUILDDIR)/$$file $(BINDIR)/" ;\ echo "R---: %attr(0755,root,root) $(BINDIR)/`basename $$file`" ;\ done ;\ echo ;\ fi efibootmgr-0.12/tools/000077500000000000000000000000001253162235600147365ustar00rootroot00000000000000efibootmgr-0.12/tools/install.pl000077500000000000000000000053151253162235600167500ustar00rootroot00000000000000#!/usr/bin/perl -w #Pragmas use strict; #Parse command line... my ($copy, $link); my $type = shift @ARGV; if( $type =~ /^copy$/i ) { $copy = 1; } if( $type =~ /^link$/i ) { $link = 1; } #Main program loop open (RPMOUT, "> filelist-rpm") or die; while( <> ){ chomp; s/^\s*//; s/\s*$//; s/\s*#.*$//; next if m/^$/; my $line = $_; ($line =~ m/^R...:(.*)/) && print RPMOUT $1 . "\n"; ($line =~ m/^..M.:(.*)/) && MakeDir( $1 ); ($line =~ m/^.C..:(.*)/) && ($copy) && CopyFile( $1 ); ($line =~ m/^.C..:(.*)/) && ($link) && LinkFile( $1 ); ($line =~ m/^R...:(.*)/) && ChangeAttrs( $1 ); } sub CopyFile { my ($src, $dst) = ParseCLine( shift ); if( -d $dst ) { $src =~ m|^.*/(.*)$|; my $file = $1; $dst .= "/" if ! ($dst=~m|/$|); $dst .= $file; } if( -e $dst ) { unlink $dst; } open INPUT, "<", $src or goto out1; open OUTPUT, ">", $dst or goto out2; while(){ print OUTPUT $_ } close OUTPUT; print "Installed File: $dst\n"; out2: close INPUT; out1: return; } sub LinkFile { my ($src, $dst) = ParseCLine( shift ); if( -d $dst ) { $src =~ m|^.*/(.*)$|; my $file = $1; $dst .= "/" if ! ($dst=~m|/$|); $dst .= $file; } if( -e $dst ) { unlink $dst; } symlink $src, $dst or warn "Linking $src to $dst failed $!\n"; print "Installed File: $dst\n"; } sub ParseCLine { my $line = shift; $line =~ s/^\s*//; $line =~ s/\s*$//; $line =~ m/^(.*?)\s+(.*?)$/; return ($1, $2); } sub ParseRLine { my $line = shift; my @directives; my @retval; $line =~ s/^\s*//; $line =~ s/\s*$//; my @words = split( /\s+/, $line ); foreach my $word (@words) { if( $word =~ /^\%(.*)/ ) { push @directives, $word; } else { push @retval, $word; } } return \@retval, \@directives; } sub MakeDir { #R-M-: %attr(0755,root,ali) /opt/ali my $line = shift; #$line =~ m/\%attr\((.{1,5}),(\w+),(\w+)\)\s+(.*)/; my ($file_ref, $directive_ref) = ParseRLine( $line ); my $dir = $file_ref->[0]; if( ! -d $dir ) { mkdir $dir or warn "Make Dir: -->$dir<-- failed $!\n"; } print "Made Dir: $dir\n"; } sub GetUID { my $name = shift; my (undef, undef, $uid, undef) = getpwnam( $name ) ; $uid = defined($uid) ? $uid : -1; return $uid; } sub GetGID { my $name = shift; my (undef, undef, $gid, undef) = getgrnam( $name ) ; $gid = defined($gid) ? $gid : -1; return $gid; } sub ChangeAttrs { my $line = shift; my ($file_ref, $directive_ref) = ParseRLine( $line ); my ($attr) = grep { /^\%attr/ } @$directive_ref; $attr =~ m/\%attr\((.{1,5}),(\w+),(\w+)\)/; my $perms = $1; my $owner = $2; my $group = $3; my $file = $file_ref->[0]; my $uid = GetUID($owner); my $gid = GetGID($group); chown $uid, $gid, $file; chmod oct($perms), $file; }